先带着几个问题来看文章:
为什么要有初始化列表、怎么写初始化列表,初始化列表的好处是什么;
1:为什么要有初始化列表:
很简单,为了提高效率和C++风格化,先说C++风格化,如果我们要在一个构造函数中初始化很多个变量,且要在构造函数中进行其他操作,那么如果我们将赋值语句和其他操作的语句放在一起,那么程序的可读性就会变得很差,而初始化列表就可以很好地解决问题,因为它是允许在函数开始前进行赋值的,而提高效率这一块本菜将在下面讲到;
2:怎么写初始化列表:
本菜感觉一般设计到书写语法的时候就是最轻松的时候:
class A {
int x, y, z;
public:
A(int x1, int y1, int z1)
:z(z1), y(y1), x(x1)
{ other }
void out()const {
std::cout << x << ' ' << y << ' ' << z << std::endl;
}
};
里面的构造函数的形参列表下面的就是初始化列表,打一个冒号,然后在成员变量后边用括号括起对应的形参,上面的初始化列表相当于:
x=x1,y=y1,z=z1
然后在花括号中写一些操作语句,这样就将赋值语句和操作语句分开了;
这里还有一个有趣的点,那就是赋值顺序,C++初始化列表是按照其中成员变量的声明顺序进行的,即上面的初始化列表尽管是z的赋值语句在x的前面,但是赋值顺序却是x->y->z,这是因为A类在变量声明顺序就是如此;
3:初始化列表的好处是什么:
上面已经解答了风格化、增加代码可读性,现在来回答初始化列表是怎么提高效率的;
看以下代码:
#include
#include
class temp {
public:
int x;
temp() {
std::cout << "Create temp" << std::endl;
}
temp(int y){
std::cout << "Create temp" << std::endl;
}
};
class A {
temp x;
public:
A() {
x = temp(8);
}
};
int main() {
A y;
}
运行结果是:
为什么会构建两次temp呢?
原因很简单,第一次是构建A类变量y的同时构建的temp类成员变量x,所以调用了一次构造函数;
第二次是因为调用A的构造函数时给x赋值的语句构建了一个无名的temp实例,然后将无名实例赋值给x,最后将无名实例抛弃;
如果我们用初始化列表给x赋值呢:
#include
#include
class temp {
public:
int x;
temp() {
std::cout << "Create temp" << std::endl;
}
temp(int y){
std::cout << "Create temp" << std::endl;
}
};
class A {
temp x;
public:
A() :x(temp(8)){
}
};
int main() {
A y;
}
运行结果:
我们只创建了一遍!
所以可以节省内存和时间的开支,嗯~使用初始化列表可真是个明智的决定呢;
那少了的哪个temp实例呢?很简单,系统会看扫描构造函数初始化列表,其中被赋值的成员变量将在实例化类的时候不被实例化,而是在调用构造函数时实例化对应的变量;