参考C++ Prime 第四版 14.5
成员初始化列表和构造函数赋值语句的区别
1.先看下面的例子
class Account {
public:
Account(const String name, double balance = 0.0);
private:
double _balance;
String _name;
};
对于构造函数的实现有两种方式:
方式1:
Account::Account(const String name, double balance) {
_name = name;
_balance = balance;
}
方式2:
Account::Account(const String name, double balance):_name(name) {
_balance = balance;
}
在两种方式最终实现的效果是一样,但是其执行过程是有很大差别的,该差别主要是给据成员变量的类型区分。
成员类的执行过程
1.构造函数的执行有两个过程:
过程1:隐式或显示初始化,该初始化也包含两个部分:
1.给据继承关系,调用基类的构造函数,该步很好的理解
2.执行所有成员类对象的默认构造函数,该步很容易被遗忘
其中隐式还是显式的初始化,就取决于是否存在成员初始化列表,如果用初始化列表则是县式调用构造函数,否则是
隐式的。
过程2:一般的计算阶段,即执行函数体中的语句,该过程是一个赋值过程
2.由此看来方式1的构造函数实现:
首先:隐式的调用了_name的默认构造函数,如果String中没有默认构造函数编译不会通过。
然后:执行函数体的赋值语句,调用了String类的拷贝赋值函数。
方式2的构造函数实现:显示的调用了相应的构造函数
方式2比方式1要高效,并且两种方式对成员类对象的构造也不同。
下面是代码实验,根据林锐博士高质量c++编程中的实现方式,编写String类的实现方式:
class String {
public:
/*String();*/
String(const char * str);
String(const String& other);
~String();
String& operator= (const String& other);
private:
char *m_data;
};
String::String(const char *str) {
cout<<"char* constructor"<<endl;
if (NULL == str) {
m_data = new char[1];
m_data[0] = '/0';
}
else {
int len = strlen(str);
m_data = new char[len + 1];
strcpy(m_data, str);
}
}
String::~String() {
delete[] m_data;
}
String::String(const String& other) {
int len = strlen(other.m_data);
m_data = new char[len + 1];
strcpy(m_data, other.m_data);
}
String& String::operator =(const String &other) {
cout<<"assignment constructor"<<endl;
if (this == &other)
return *this;
delete[] m_data;
int len = strlen(other.m_data);
m_data = new char[len + 1];
strcpy(m_data, other.m_data);
return *this;
}
/*String::String() {
cout<<"default constructor"<<endl;
m_data = new char[1];
m_data = '/0';
}*/
按照方式2执行下列语句
int _tmain(int argc, _TCHAR* argv[])
{
Account *account = new Account("steven");
return 0;
}
执行结果:屏幕打印 "char* constructor"
按照方式1执行该语句
编译报错:error C2512: “String”: 没有合适的默认构造函数可用,由此说明调用了默认构造函数。
我们把上面的注释去掉,继续执行
执行结果,屏幕打印:
char* constructor
default constructor
assignment constructor
对于内置类型的初始化
1.对于const数据成员和引用数据成员只能在构造函数处是化
2.其他类型应该等价
关于成员初始化成员列表的执行顺序:
成员处是换的执行顺序是根据根据成员的声明顺序执行的,并不根据成员列表的书写顺序,从该点来看,如果成员变量的初始化有顺序的换,还是把赋值放在函数体内比较清晰。