构造函数初始列表与体内赋值辨析

构造函数初始列表与体内赋值辨析

1、初始化列表与赋值区别

1) 初始化代表为变量分配内存,变量在其定义处被编译器初始化(编译时);在函数中, 函数参数初始化发生在函数调用时(运行时)。然而,赋值代表"擦除对象当前值, 赋予新值",不承担为对象分配内存的义务。

2)对于内置类型,初始化列表与体内赋值性能差距不大;但对于复杂的内对象,初始化列表无需调用默认构造函数,从而提高程序性能

eg1:

#include <iostream>

using std::cout;
using std::endl;

struct Test1
{
	Test1()
	{
		cout << "Construct Test1" << endl;
	}

	Test1(const Test1& t1) // 
	{
		cout << "Copy constructor for Test1" << endl;
		this->a = t1.a;
	}

	Test1& operator = (const Test1& t1)
	{
		cout << "Assignment for Test1" << endl;
		this->a = t1.a;
		return *this;
	}

	int a;
};

struct Test2
{
	Test1 test1;
	Test2(Test1 &t1)
	{
		test1 = t1;
	}
};

int main(int argc, char* argv[])
{
	Test1 t1;
	Test2 t2(t1);
	return 0;
}

输出结果:

Construct Test1

Copy constructor for Test1

Assignment for Test1

eg2:

#include <iostream>

using std::cout;
using std::endl;

struct Test1
{
	Test1()
	{
		cout << "Construct Test1" << endl;
	}

	Test1(const Test1& t1) // 
	{
		cout << "Copy constructor for Test1" << endl;
		this->a = t1.a;
	}

	Test1& operator = (const Test1& t1)
	{
		cout << "Assignment for Test1" << endl;
		this->a = t1.a;
		return *this;
	}

	int a;
};

struct Test2
{
	Test1 test1;
	Test2(Test1 &t1) :test1(t1) {
	}
};

int main(int argc, char* argv[])
{
	Test1 t1;
	Test2 t2(t1);
	return 0;
}
输出结果:
Construct Test1
Copy constructor for Test1
比较eg1和eg2的输出结果可知,使用初始化列表减少了一次调用默认构造函数。


注:根据成员在类中声明的顺序决定初始化列表成员的顺序,否则会出现未定义的行为。


2、必须使用初始化列表

1)常量成员

常量只能初始化,不能赋值

eg:

class A
{
	const int x;
public:
	A( ){
		this->x = 1;
	}
};

等价于:

const int x;
x = 1;
正确方式:
class A
{
	const int x;
public:
	A() : x(1){
	}
};

2)引用成员
引用必须在定义时初始化,且初始化后不能重新赋值

eg:

class A {
	int &x;
public:
	A(int k) {
		this->x = k;
	}
};

等价于:

int &x;
int k;
x = k;

正确方式:

class A {
	const int x;
public:
	A(int k) : x(k) {
	}
};


3)没有默认构造函数的类类型

初始化列表不需要调用构造函数初始化,而是直接调用拷贝构造函数初始化

eg:

struct Test1
{
	Test1(int a) :i(a) {}
	int i;
};

struct Test2
{
	Test1 test1;
	Test2(Test1 &t1)
	{
		test1 = t1;
	}
};

正确方式:

struct Test1
{
	Test1(int a) :i(a) {}
	int i;
};

struct Test2
{
	Test1 test1;
	Test2(Test1 &t1) :test1(t1) {}
};

3、选择规则

1) 所有static成员变量在类外初始化(不管它是const,是引用,还是没默认构造函数的对象)

2)对于常量成员、引用成员及没有默认构造函数的类类型必须在初始化列表初始化

3)需要复杂运算及资源分配时,使用在构造函数内赋值;否则,尽量在初始化列表中初始化。


参考文献

[1] C++类构造函数初始化列表. http://www.cnblogs.com/BlueTzar/articles/1223169.html.

[2]【深入理解C++】从初始化列表和构造函数谈C++的初始化机制. http://blog.csdn.net/theprinceofelf/article/details/20057359.

[3] 成员初始化列表与构造函数体中的区别详细解析. http://www.jb51.net/article/41812.htm.

[4] 我所理解的构造函数的初始化列表(转). http://blog.sina.com.cn/s/blog_4c5c3e0501000am7.html.

[5] Constructorinitialization Vs assignment. http://stackoverflow.com/questions/15679977/constructor-initialization-vs-assignment.

[6] initializationlists vs explicit assignment. http://www.cplusplus.com/forum/general/114874/.

[7] c++初始化列表及构造函数调用构造函数. http://blog.csdn.net/mrluoming/article/details/7614042.

[8]C++初始化列表. http://www.cnblogs.com/graphics/archive/2010/07/04/1770900.html


注:为了便于自己学习,无心侵权,尽可能将所引用的文章列举出来;有些文章的内容可能会与原作重复度较高,还请谅解。如作者举报,愿意删除此文。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值