modern c++的写法思考之成员变量默认值

在构造函数中使用初始化列表(Initializer List),能够使执行效率更高,能使得成员变量在创建时即初始化,同时要求初始化列表的顺序与成员变量的声明顺序一致。

现代 c++的类成员,可以在声明成员变量时直接写好默认值,这种方法叫法brace-or-equal-initializers,即使用花括号和等号均可,同时任何静态的函数或者变量都可以作为初始值,尽管这会带来一些消耗,但能够很好的防止奇葩问题的发生。

static int _default_age() {
    return 88;
}

class Student
{
    string name_ = "anonymous";
    int age_ = _default_age();
};

在以往,我们创建一个结构体时,需要memset一把,来把该块内存初始化为0,而如果里面有涉及string或者vector之类的成员变量,又有我们想初始化为0的int/float,就只能一个一个赋值了,这让代码变得冗长。而现代c++提供了默认的办法,可以更合理地『清零』,即普通类型置0,有默认构造函数的调用构造函数。使用空的花括号即搞定:

struct Info
{
    string favo_food;
    float weight;
    int height;
};
Info info = {};

未初始化的变量,在debug模式下可能会由编译器帮忙置0,但是在开启优化的release模式下,就会变成各种乱七八糟的值了。

这时就出现一个优先次序问题了:如果构造函数里既使用了初始化列表,变量声明也设置了默认值,而结构体类型的变量也设置了默认清零,结果会是如何呢?

static int _default_age() {
    return 88;
}

struct Info
{
    string favo_food;
    float weight;
    int height = 99;
};

class Student
{
public:
    Student() {};
    Student(const char *name, int age) : name_(name), age_(age) {
    }

    void print_info() {
        cout << name_ << " " << age_ << endl;
        cout << info_.favo_food << " " << info_.weight << " " << info_.height << endl;
    }

private:
    string name_ = "anonymous";
    int age_ = _default_age();
    Info info_ = {};
};

int main()
{
    Student s;
    s.print_info();
    Student s2("zhang san", 100);
    s2.print_info();
    return 0;
}

结果非常合理且易于理解:构造函数的初始化列表会覆盖声明时的默认值,info_ = {}只会对没有默认值的字段做清零操作。

发表于 2018年10月12日 10:40   评论:0   阅读:4128  



回到顶部

首页 | 关于我 | 关于本站 | 站内留言 | rss
python logo   django logo   tornado logo