C++ 初始化列表
1.初始化列表的写法
初始化列表,写在类的构造函数后面,以冒号开头,后跟一系列用逗号分隔的初始化字段。如下列所示:
class Person { public: Person(std::string s, int i):name(s), age(i) { std::cout<<"Person(std::string s, int i)"<<std::endl; } ; private: std::string name ; int age; };
其中的:name(s), age(i){} 即为初始化列表,创建对象时,有两个步骤:
成员变量初始化阶段:会将对象中的变量进行初始化,就是初始化列表,示例中我们自定义了部分变量初始化的方式。
构造函数执行阶段:执行构造函数中的代码。
下面的示例说明了以上的两个步骤,我们给Person类增加一个Pet字段,
这样在创建Person对象时,会先初始化成员变量,执行Pet的构造函数,再执行Person的构造函数:
class Pet { public: Pet() { std::cout<<"Pet()"<<std::endl; } private: std::string category; }; class Person { public: Person(std::string s, int i):name(s), age(i) { std::cout<<"Person(std::string s, int i)"<<std::endl; } ; private: std::string name ; int age; Pet pet; }; int main() { Person("Jack",20); return 0; }
输出结果:
Pet()
Person(std::string s, int i)
2.使用初始化列表的好处
在上例中,每次初始化Person对象时都会调用Pet的构造函数,如果使用初始化列表,则在成员变量初始化步骤时,可以用一个已经存在的Pet对象,直接赋给Person的Pet字段,省略了调用Pet构造函数的过程,提高了效率。
代码示例如下:
class Pet { public: Pet() { std::cout<<"Pet()"<<std::endl; } private: std::string category; }; class Person { public: Person(std::string s,int i,Pet p):name(s), age(i),pet(p) { std::cout<<"Person(std::string s, int i)"<<std::endl; } ; private: std::string name ; int age; Pet pet; }; int main() { Pet pet; Person("Jack",20,pet); return 0; }
3.必须使用初始化列表的几种情况
1)常量成员,因为常量只能初始化不能赋值,所以必须放在初始化列表里面
class Test { public: Test(int i):a(i){}; private: const int a; }
2)引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要写在初始化列表里面
class Test { public: Test(int i):a(i){}; private: int& a; }
3)没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用拷贝构造函数初始化。
class Test { public: Test(int i):a(i){}; private: int a; }
4)类继承中,基类私有字段的初始化有时必须通过在初始化列表中调用基类的构造函数
#include<iostream> class Test { public: Test(int i):a(i){}; void Show() { std::cout<<a<<std::endl; } private: int a; }; class SubTest:public Test { public: SubTest(int i):Test(i){} }; int main() { SubTest subtest(5); subtest.Show(); return 0; }
4.成员变量的初始化顺序
成员是按照他们在类中出现的顺序进行初始化的,而不是按照他们在初始化列表出现的顺序初始化的,看代码。
class Test { public: Test(int x):j(x), i(j){} private: int i ; int j ; };
代码会报错,因为类中i限于j定义,所以用j初始化i时,会报错j还没有初始化。