C++中成员初始化列表的使用

原创 2012年03月27日 11:42:11
 C++在类的构造函数中,可以两种方式初始化成员数据(data member)。
1,在构造函数的实现中,初始类的成员数据。诸如:
class point
{
private:
 int x,y;
public:
 point(int m=0,int n=0)
 {
  x=m;
  y=n;
 }
 int GetX()
 {
  return x;
 }
 int GetY()
 {
  return y;
 }
};
2,还可以定义初始化成员列表(Initializer list)来初始化成员数据(data member)。
  改写构造函数如下:
 point(int m=0,int n=0):x(m),y(n)
 {
 }
这样咋一看没有什么不同,确实,对于上面的这种简单列子来说,也真的没有太大不同。
 
那我们为什么要用初始化成员列表,什么时候用初始化成员列表来初始化成员数据呢?Lippman的《C++ Primer》中提到在以下三种情况下需要使用初始化成员列表:
 
一,需要初始化的数据成员是对象的情况;
二,需要初始化const修饰的类成员;
三,需要初始化引用成员数据;
 
现在分别举例说明:
一,需要初始化的数据成员是对象。
---------------------------
#include <stdio.h>
class point
{
protected:
 int m_x,m_y;
public:
 point(int m=0,int n=0)
 {
  m_x = m;
  m_y = n;
  printf("constructor called!/n");
 }
 point(point& p)
 {
  m_x = p.GetX();
  m_y = p.GetY();
  printf("copy constructor called!/n");
 }
 int GetX()
 {
  return m_x;
 }
 int GetY()
 {
  return m_y;
 }
};
 
class point3d
{
private:
 point m_p;
 int m_z;
public:
 point3d(point p, int k)
 {
  m_p = p;                              //这里是对m_p的赋值
  m_z=k;
 }
 point3d(int i,int j, int k):m_p(i,j)   // 相当于 point m_p(i,j)这样对m_p初始化
 {
  m_z=k;
 }

 void Print()
 {
  printf("%d,%d,%d /n",m_p.GetX(),m_p.GetY(),m_z);
 }
};
---------------------------------------
上述代码中Point3d是一个3D坐标,他有一个point的2D坐标和一个成员组成。
我们现在想定义一个3D坐标p3d,可以这样实现:
void main()
{
 point p(1,2);    //先定义一个2D坐标
 point3d p3d(p,3);
 p3d.Print();
}
从point3d实现体可以看出,我们是通过对m_p进行赋值,这样不仅调用copy constructor产生临时对象而且是对m_p的一个赋值操作。
而如果使用成员初始化列表,我们则可以这样:
void main()
{
 point p(1,2);
 point3d p3d(1,2,3);
 p3d.Print();
}
p3d中的point型成员是通过调用初始化的方式构建的。由于对象赋值比初始化要麻烦的多,因此也带来的性能上的消耗。(可以参见Scott Meyers著《effective C++》条款12)。
这也是我们在对成员数据是对象成员的采用初始化列表进行初始始化的主要原因。
 
二,需要初始化const修饰的类成员;
三,需要初始化引用成员数据;
对于类成员是const修饰,或是引用类型的情况,是不允许赋值操作的,(显然嘛,const就是防止被错误赋值的,引用类型必须定义赋值在一起)因此只能用初始化列表对齐进行初始化。
上面两点比较好明白,可以用一个例子加以说明:
-------------------------------------
#include <stdio.h>
class base
{
private:
 const int a;
 int& b;
public:
// base(int m, int n)
// {
//  a = m;
//  b = n;
// }
 base(int m, int n):a(m),b(n)
 {}
};
 
void main()
{
 base ba(1,2);
}
---------------------------
上面红色的部分初始化的方式是不允许的通不过编译,通过初始化列表则可以很好的定义。

C++必须使用【初始化列表】初始化数据成员的三种情况

类对象的构造顺序是这样的: 1.分配内存,调用构造函数时,隐式/显示的初始化各数据成员; 2.进入构造函数后在构造函数中执行一般赋值与计算。 使用初始化列表有两个原因: 原因1.必须这样做: ...
  • sinat_20265495
  • sinat_20265495
  • 2016年12月15日 15:13
  • 4253

C++为什么需要成员初始化列表

将构造函数分为两个阶段的执行过程:初始化阶段和构造函数函数体阶段。 既然称它为成员初始化列表,那么该阶段在初始化阶段完成。 那么类成员变量不外乎类类型和非类类型。而对于非类类型而言,此时 无论是...
  • WS1347913745
  • WS1347913745
  • 2013年03月16日 23:01
  • 2345

C++成员初始化列表详解

C++成员初始化列表详解 在初始化类的成员的时候,我们经常会有两种选择,其一是类构造函数的成员初始化列表,其二是构造函数的函数体。那么这两者的区别又是什么,成员初始化列表的具体行为到底是...
  • Poundssss
  • Poundssss
  • 2015年10月24日 11:22
  • 5017

C++类构造函数初始化列表及初始化成员变量的误区

构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。例如: class CExample { public: int a; f...
  • sinat_20265495
  • sinat_20265495
  • 2016年12月14日 20:13
  • 1599

C++成员变量初始化顺序

1、成员变量在使用初始化列表初始化时,与构造函数中初始化成员列表的顺序无关,只与定义成员变量的顺序有关。因为成员变量的初始化次序是根据变量在内存中次序有关,而内存中的排列顺序早在编译期就根据变量的定义...
  • MM_dou
  • MM_dou
  • 2017年01月15日 14:47
  • 616

c++11---统一的初始化和初始化列表

在c++11以前,程序员,或者初学者经常回干
  • u011619422
  • u011619422
  • 2014年04月22日 20:02
  • 3399

C++类中成员变量的初始化总结

FROM: http://blog.csdn.net/gljseu/article/details/9750877 1、普通的变量:一般不考虑啥效率的情况下 可以在构造函数中进行赋值。考虑一下效率的...
  • gaoxuelin
  • gaoxuelin
  • 2013年08月05日 13:55
  • 10165

C++初始化列表

与其他函数不同,构造函数除了有名字,参数列表和函数体之外,还可以有初始化列表,初始化列表以冒号开头,后跟一系列以逗号分隔的初始化字段。 class foo {       public:   ...
  • u010481185
  • u010481185
  • 2014年01月05日 18:36
  • 836

c++构造函数成员初始化中赋值和初始化列表两种方式的区别

先总结下: 由于类成员初始化总在构造函数执行之前 1)从必要性:      a. 成员是类或结构,且构造函数带参数:成员初始化时无法调用缺省(无参)构造函数      b. 成员是常量或引用:...
  • zizi7
  • zizi7
  • 2016年08月31日 11:26
  • 5460

关于C++ 类数据成员初始化的一点总结【为什么类定义中不能初始化成员变量】

往往被初学者忽视的是,C++类中的数据初始化是有jia
  • qqaiustc
  • qqaiustc
  • 2014年08月22日 00:10
  • 3566
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++中成员初始化列表的使用
举报原因:
原因补充:

(最多只允许输入30个字)