既然构造函数初始化列表和构造函数体内赋值都可以对成员变量赋值,那么二者有何区别,是不是二者等效呢?


一、若类的数据成员是静态的(const)和引用类型,必需用初始化列表


静态(const)的数据成员只能初始化而不能赋值,同样引用类型也是只可以被初始化,那么只有用初始化列表。


如:

#include <iostream>  
#include <string>
using namespace std;

template<class t>
class namedptr {
public:
namedptr(const string& initname, t *initptr);
private:
const string name; //静态数据成员的初始化必需用初始化列表
t * const ptr;
};



template<class t>
namedptr<t>::namedptr(const string& initname, t *initptr )
: name(initname), ptr(initptr)
{}

//第二种方法是在构造函数体内赋值:

//template<class t>
//namedptr<t>::namedptr(const string& initname, t *initptr)
//{
// name = initname;
// ptr = initptr;
//}


int main()
{
int a = 10;
namedptr<int> Test("SHENZHEN",&a);
}

 

由于 const string name; //静态数据成员的初始化必需用初始化列表

t * const ptr;

是静态的,如果用构造函数体内赋值,编译会出错。


二、构造函数体内赋值会带来额外的开销,效率会低于构造函数初始化列表


上面的例子改一改:

 

C++代码 

template<class t>  
class namedptr {
public:
namedptr(const string& initname, t *initptr);
private:
string name;
t * ptr;
};


并且用这两中初始化方法做对比:

C++代码 

//第一种方法:初始化列表  
template<class t>
namedptr<t>::namedptr(const string& initname, t *initptr )
: name(initname), ptr(initptr)
{}

//第二种方法是在构造函数体内赋值:

template<class t>
namedptr<t>::namedptr(const string& initname, t *initptr)
{
name = initname;
ptr = initptr;
}


当用第二种方法初始化数据成员时会两次对string的成员函数的调用:一次是缺省构造函数,另一次是赋值。


而用第一种方法(初始化列表)只是一次调用缺省的构造函数,并不会调用赋值函数。会减少不必要的开支,当类相当复杂时,就会看出使用初始化列表的好处。