C++初始化成员列表

C++在类的构造函数中,可以两种方式初始化成员数据:

  • 在构造函数的实现中,初始类的成员数据。
  • 还可以定义初始化成员列表 (Initializer list) 来初始化成员数据。

 

那么我们在什么情况下该使用初始化成员列表呢?

  1. 需要初始化的数据成员是对象。
  2. 需要初始化的类成员是const对象或者引用对象。
  3. 解决没有默认构造函数的类成员对象的生成。
  4. 在继承里面,只有初始化列表可以构造父类的private成员。

 

 

1. 需要初始化的数据成员是对象。

 

Cpp代码   收藏代码
  1. #include <stdio.h>  
  2. class point  
  3. {  
  4.     protected:  
  5.         int m_x,m_y;  
  6.   
  7.     public:  
  8.         point(int m=0,int n=0)  
  9.         {  
  10.             m_x = m;  
  11.             m_y = n; 
  12.             printf("constructor called!\n"); 
  13.         }  
  14.   
  15.         point(point& p)  
  16.         {  
  17.             m_x = p.GetX();  
  18.             m_y = p.GetY();  
  19.             printf("copy constructor called!\n");
  20.         }  
  21.   
  22.         int GetX()  
  23.         {  
  24.             return m_x;  
  25.         }  
  26.   
  27.         int GetY()  
  28.         {  
  29.            return m_y;  
  30.         }  
  31. };  
  32.    
  33. class point3d  
  34. {  
  35.     private:  
  36.     point m_p;  
  37.     int m_z;  
  38.   
  39.     public:  
  40.         point3d(point p, int k)  
  41.         {  
  42.             m_p = p;  
  43.             m_z=k; 
  44.         }  
  45.   
  46.          point3d(int i,int j, int k):m_p(i,j)   // 相当于 point m_p(i,j)这样对m_p初始化  
  47.          {  
  48.              m_z=k;  
  49.          }  
  50.   
  51.          void Print()  
  52.          {  
  53.              printf("%d,%d,%d \n",m_p.GetX(),m_p.GetY(),m_z);  
  54.          }  
  55. };  

 

   我们可以使用如下进行初始化,它将调用拷贝构造函数:

   关于拷贝构造函数,可参见 http://www.cnblogs.com/BlueTzar/articles/1223313.html

 

Cpp代码   收藏代码
  1. void main()  
  2. {  
  3.     point p1(1,2);    //先定义一个2D坐标  
  4.     point3d p3d(p1,3);  
  5.     p3d.Print();  
  6. }  

 输出:

constructor called!
copy constructor called!
constructor called!
1,2,3 

为什么呢?

第一个constructor called!是构造p1;

第二个copy constructor called!是把p1传入函数p3d的p时,因为函数形参的赋值操作时一个使用拷贝构造函数的过程。会调用拷贝构造函数把p1拷贝到p;

第三个constructor called!是point3d p3d(p,3)这个构造函数执行时,首先按顺序初始化所有的成员列表,然后执行函数体。初始化列表时,虽然我们没有显示的告诉它怎么初始化,但是此时编译器会用默认值进行初始化,一般是0。对于其中的成员变量m_p,会采用默认的无参数构造函数。(如果没有默认的无参构造函数,此时编译会报错,解决方法是,在初始化列表里显示的使用有参构造)至于m_p=p这个怎么运行呢,这里不会调用拷贝构造函数,因为拷贝构造函数也是一种构造函数,只有在心间对象时会调用,此处调用的是=号运算符,如果我们没有定义这个运算符操作,则编译器会自己合成一个按位拷贝的=号操作运算函数。


   也可以使用初始化成员列表进行初始化:

 

Cpp代码   收藏代码
  1. void main()  
  2. {  
  3.     point3d p3d(1,2,3);  
  4.     p3d.Print();  
  5. }  

 

输出:

constructor called!
1,2,3 


只调用了一次constructor called!,这次调用是在上面那种里的第三个constructor called!,构造成员变量m_p,在初始化列表里,使用含参构造



   由于对象赋值比初始化要麻烦的多,因此也带来的性能上的消耗。所以使用初始化列表可以更高效地初始化成员变量是对象的情况。

 

 

2. 需要初始化的类成员是const对象或者引用对象。

 

对于类成员是const修饰,或是引用类型的情况,是不允许赋值操作的,、因此只能用初始化列表对其进行初始化。

 

Cpp代码   收藏代码
  1. #include <stdio.h>  
  2. class base  
  3. {  
  4.     private:  
  5.         const int a;  
  6.         int& b;  
  7.   
  8.     public:  
  9.          // base(int m, int n)  
  10.          // {  
  11.          //  a = m;  
  12.          //  b = n;  
  13.          // }  
  14.   
  15.          base(int m, int n):a(m),b(n)  
  16.          {}  
  17. };  
  18.    
  19. void main()  
  20. {  
  21.     base b(1,2);  
  22. }  

 

其中,注释的部分将无法通过编译。

 

 

3. 解决没有默认构造函数的类成员对象的生成。

 

如果成员类型是没有默认构造函数的类。若没有提供显示初始化,则编译器隐式使用成员类型的默认构造函数,若该类没有默认构造函数,则编译器尝试使用默认构造函数将会失败。

 

 

4. 在继承里面,只有初始化列表可以构造父类的private成员。

 

 

原文地址:http://blog.youkuaiyun.com/freedom0203/article/details/2805945

### C++ 初始化成员列表的用法与示例 在C++中,初始化成员列表(Initializer List)是一种用于在构造函数初始化成员的有效方法。它不仅提高了代码的可读性,还避免了不必要的默认构造和赋值操作,从而提升程序性能[^1]。 #### 基本语法 初始化成员列表的基本语法如下: ```cpp ClassName::ClassName(参数列表) : 成员变量1(初始值1), 成员变量2(初始值2), ... { // 构造函数体 } ``` #### 示例代码 以下是一个使用初始化成员列表的完整示例: ```cpp #include <iostream> using namespace std; class Point { public: // 构造函数使用初始化成员列表 Point(int x, int y) : _x(x), _y(y) {} void print() { cout << "Point(" << _x << ", " << _y << ")" << endl; } private: int _x; // 成员变量 int _y; // 成员变量 }; int main() { Point p(3, 5); // 创建对象并初始化 p.print(); // 输出结果 return 0; } ``` 在这个例子中,`_x` 和 `_y` 是通过初始化成员列表直接初始化的,而不是在构造函数体内进行赋值。这种方式更加高效,因为避免了先调用默认构造函数再赋值的过程[^4]。 #### 解决的问题 初始化成员列表解决了以下问题: 1. **常量成员初始化**:如果类中包含 `const` 类型的成员变量,则必须通过初始化成员列表进行初始化,而不能在构造函数体内赋值[^3]。 2. **引用成员初始化**:对于引用类型的成员变量,只能通过初始化成员列表进行初始化。 3. **提高效率**:相比于在构造函数体内赋值,初始化成员列表直接在内存分配时完成初始化,减少了额外的操作。 4. **防止类型窄化**:初始化成员列表可以防止隐式类型转换导致的精度丢失[^3]。 #### 注意事项 - 初始化顺序由成员变量在类中声明的顺序决定,而非初始化列表中的顺序[^1]。 - 如果初始化列表中未显式初始化某个成员变量,则会尝试使用其默认构造函数或默认初始化器[^2]。 #### 运行结果分析 针对用户提供的代码片段,以下是运行结果的详细分析: ```cpp #include <iostream> using namespace std; class A { public: A(int a) : _a1(a), _a2(_a1) {} // 初始化列表 void Print() { cout << _a1 << " " << _a2 << endl; } private: int _a2 = 2; // 默认成员初始化器 int _a1 = 2; // 默认成员初始化器 }; int main() { A aa(1); aa.Print(); } ``` 在此代码中,`_a1` 和 `_a2` 的初始化顺序由它们在类中声明的顺序决定。尽管 `_a2` 在初始化列表中被指定为 `_a2(_a1)`,但由于 `_a2` 的初始化发生在 `_a1` 之前(根据声明顺序),此时 `_a1` 尚未被正确初始化,因此 `_a2` 的值是未定义的。最终输出结果为 `1 随机值`[^2]。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值