C++中为什么构造函数初始化列表?
在以下三种情况下需要使用初始化成员列表:
一,需要初始化的数据成员是对象的情况;
二,需要初始化const修饰的类成员;
三,需要初始化引用成员数据;
需要初始化引用成员数据
最近才发现C++可以定义引用类型的成员变量,引用类型的成员变量必须在构造函数的初始化列表中进行初始化。对于类成员是const修饰,或是引用类型的情况,是不允许赋值操作的,(显然嘛,const就是防止被错误赋值的,引用类型必须定义赋值在一起)因此只能用初始化列表对齐进行初始化。
#include <iostream>
using namespace std;
class Test
{
private:
int &a;
public:
Test(int &b) : a(b)
{
}
void Modify(int value)
{
a = value;
}
};
int main()
{
int b = 3;
Test test(b);
cout <<"b="<<b<<endl;
test.Modify(4);
cout <<"b="<<b<<endl;
return 0;
}
需要初始化const修饰的类成员
#include <iostream>
using namespace std;
class base
{
public:
const int a;
int& b;
public:
// base(int m, int n)
// {
// a = m;
// b = n;
// }
base(int m, int n):a(m),b(n)
{}
};
int main()
{
base ba(1,2);
cout << ba.a <<endl;
cout << ba.b <<endl;
}
需要初始化的数据成员是对象的情况
#include <iostream>
using namespace std;
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,可以这样实现:
int main()
{
point p(1,2); //先定义一个2D坐标
point3d p3d(p,3);
p3d.Print();
}
从point3d实现体可以看出,我们是通过对m_p进行赋值,这样不仅调用copy constructor产生临时对象而且是对m_p的一个赋值操作。
而如果使用成员初始化列表,我们则可以这样:
int main()
{
point p(1,2);
point3d p3d(1,2,3);
p3d.Print();
}
p3d中的point型成员是通过调用初始化的方式构建的。由于对象赋值比初始化要麻烦的多,因此也带来的性能上的消耗。这也是我们在对成员数据是对象成员的采用初始化列表进行初始始化的主要原因。
----------------------------------------------------------------------------------------------------------------------------------------------------------C++必须用带有初始化列表的情况:
(1)成员类型是没有默认构造函数的类。若没有提供显示初始化式,则编译器隐式使用成员类型的默认构造函数,若类没有默认构造函数,则编译器尝试使用默认构造函数将会失败。
(2)const成员或引用类型的成员。因为const对象或引用类型只能初始化,不能对他们赋值。