- 作者: 雪山肥鱼
- 时间:20210825 22:29
- 目的: 成员初始化列表的作用
何时需要成员初始化列表
class Base
{
public:
int ba;
int bb;
Base(int tmpa, int tmpb)
{
}
};
class CSub
{
public:
CSub(int tmpv)
{
}
};
class A:public Base
{
public:
int m_x;
int m_y;
int &m_yy;
const int m_myc;
CSub cmysub;
//A() :m_x(0), m_y(0)
A(int &tmpvalue):m_yy(tmpvalue), m_myc(tmpvalue),Base(tmpvalue, tmpvalue), cmysub(tmpvalue)
{
//m_myc = tmpvalue;
//m_yy = tmpvalue;
m_x = 0;
m_y = 0;
m_yy = 180;
}
};
int main(int argc, char ** argv)
{
int abc =1;
A a(abc);
}
下述情况必要参数初始化列表
- 成员变量有引用
- 成员变量 是 const 类型
- 如果继承一个基类,且积累中有自定义的含参数构造函数
- 成员变量的类型是对象,且 这个类中有自己的带参数的自定义构造函数
参数列表各种试错:
![](https://img.haomeiwen.com/i25953572/c085c487b38ec748.png)
参数初始化列表的作用
无参数初始化列表
class X
{
public:
int m_i;
X(int value = 0):m_i(value)
{
cout <<"X(int)"<<" this: "<< this<<endl;
}
X(const X& tmp)
{
cout<<"Copy X(const &)"<<" this: "<<this<<endl;
}
X & operator=(const X &tmp)
{
cout<<"Operator=(const X & tmp)"<<" this: "<<this<<endl;
}
~X()
{
cout<<"X destructor"<<" this: "<<this<<endl;
}
};
class A
{
public:
X xobj;
int m_test;
/*
X xobj;
xobj.X::X(int tmp);
*/
A(int tmpvalue)//走到这里的时候 xobj 被构造
{
/*
X tmp;
tmp.X::X(1000);
xobj.X::operator=(tmp);
tmp.X::~X();
*/
xobj = 1000; //xobj 已经存在,增加 3个动作 :所以先用1000 构造一个 tmp, 然后调用operator=,最后析构
m_test = 500;
}
};
int main(int argc, char **argv)
{
A myaobj(1000);
return 0;
}
![](https://img.haomeiwen.com/i25953572/7a18778dcf140a86.png)
其实只因为 一句话 xobj = 1000 就会多出3个动作,注意这里走到 这一行的时候, xobj 已经生成了,因为 X类 的构造函数是有默认参数的。
三个动作在代码的注释已经说明。另外可以观察到临时对象和 对象 xobj 的地址并不相同!
带有参数初始化列表
class A
{
public:
X xobj;
int m_test;
int m_test2;
A(int tmpvalue):xobj(1000)
{
}
};
运行结果,会减少上一节中的三个步骤。
单步调试就可以知道,参数初始化列表是在本类的构造函数之前执行的!
变量的初始化顺序是定义顺序,而不是参数列表初始化顺序
class A
{
public:
X xobj;
int m_test;
int m_test2;
A(int tmpvalue):xobj(1000),m_test2(100),m_test(m_test2)
{
}
};
- m_test 先被初始化
- m_test2 后被初始化
- 如果像构造函数一样的顺序,则m_test还未被初始化的时候,m_test 就被赋予了垃圾值。
- 并不是我们想要的结果。
- 简单成员变量,建议在构造函数内部初始化,就不必在意顺序啦。
网友评论