查看原文
其他

类成员初始化和赋值的内幕

Linux_Daily 混说Linux 2022-11-19

定义一个变量,就是在内存中为你定义的这个变量开辟一段内存空间,如果这个变量没有初始化,那么系统会随机给这个变量赋一个值,这个值我一般称它为"垃圾数"。


没有初始化的变量我认为它是没有意义的,是在浪费内存,就比如人刚出生的时候上帝需要给他赋予点东西,比如条件反射,比如哭,比如吮吸........这样人的意义得以体现。


对于类的成员来说,我们最好的做法就是在构造函数中对每一个类成员进行初始化。


我们来看一个简单的例子:


class name{public:    name(int aa, int bb)    {}private:    int a;    int b;};


上面例子中的变量 a 和 b 的值都没有在构造函数中初始化,这时候它们的值就会是一个"垃圾数",我们稍微改一下:


class name{public:    name(int aa, int bb):a(aa)    {        b = bb;    }private: int a; int b;};


可以看到 a 的值是用初始化列表的方式进行初始化,而 b 的值是通过构造函数的参数进行赋值。


在类对象调用构造函数的时候,以上两种方式都可以确保 a 和 b 的值是可以确定的,但是初始化和赋值两种方式是有区别的

  1. 初始化发生的时机肯定比赋值早。初始化会在程序刚开始运行的时候发生,而赋值是只有在程序执行到这条语句才会发生。

  2. 初始化的执行效率要比赋值高。类成员在构造函数中执行的赋值语句之前已经被系统进行了初始化,当执行赋值的时候就需要抹掉之前default的初始化的数据,这样就相当于多做了一次无用功,而构造函数中运行的初始化列表则不需要做这次无用功。

  3. 常量成员和引用成员只能使用初始化列表。这是c++的语法。



class name{public:    name(int aa, int bb):b(bb),a(aa)    {}private: int const a; int &b;};


代码中的类成员 a 和 b 是必须使用初始化列表初始化的,这是c++语法规定的。


另外,类成员的初始化的顺序的固定的:如果有基类的话,先初始化基类,然后按照类中声明的顺序去初始化派生类中的类成员。上述代码中可以看到,构造函数初始化列表是先写 b 后写 a,即使是这样也是会按声明的顺序先初始化 a 后初始化 b。


我们来做一个实验就可以彻底明白:


class Name{public:    Name():b(2),a(b + 2)    {}        void print()    {     cout << "a = " << a << " , b = " << b << endl;    }private: int const a;    int b;};
int main(){    Name Leon;    Leon.print();  return 0;}


编译后的结果为:


结果很明显,当初始化 a 的时候,b还没被初始化为2,b还是个垃圾数,所以最终打印的 a 的值依然是个垃圾数,b 则后面被初始化为 2。





关注微信公众号『混说Linux』,后台点击 关于混说 即可添加作者微信。




往期回顾






分享是一种积极的生活态度


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存