码迷,mamicode.com
首页 > 其他好文 > 详细

构造函数初始化列表和构造函数体内赋值

时间:2015-07-24 12:54:37      阅读:105      评论:0      收藏:0      [点我收藏+]

标签:cc++

#include <iostream>
using namespace  std;

class A{
public:
	A(int a,string str)
	{
		m_a = a;
		m_str = str;
	}
	//A(int a,string str):m_a(a),m_str(str){}

	 void print()
	 {
		 cout << m_a << ' '<< m_str<< endl;
	 }

private:
	int m_a;
	string m_str;

};

int main(int argc, char **argv)
{
	A a(1,"hello");
	a.print();
	return 0;
}

运行结果相同,那么两者区别在哪里???

从概念上,我们可以认为构造函数分两个阶段执行:

(1)初始化阶段       (2)普通的计算阶段。

①不管成员是否在构造函数初始化列表中显式初始化, 类类型的数据成员总是会在初始化阶段初始化。 初始化发生在计算阶段开始之前。

②在构造函数初始化列表中没有显示提及的每个成员, 使用与初始化变量相同的规则来进行初始化。 运行该类型的默认构造函数,来初始化类类型的数据成员。 

③内置或复合类型的成员的初始值依赖于对象的作用域:在局部作用域中这些成员不被初始化,而在全局作用域中,它们被初始化为0。

④计算阶段由构造函数体内的所有语句构成。在计算阶段中,数据成员的设置被认为是赋值,而不是初始化。没有清楚地认识到这个区别是程序错误和低效的常见源泉。

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

结论:构造函数初始化列表是对类的成员做初始化,而在构造函数体内只是对类的数据成员进行了一次赋值操作。


1. 初始化列表存在的价值:

首先把数据成员按类型分类并分情况说明:
①.内置数据类型,复合类型(指针,引用)
    在成员初始化列表和构造函数体内进行,在性能和结果上都是一样的
②.用户定义类型(类类型)
     结果上相同,但是性能上存在很大的差别。更受欢迎的实现是用成员初始化表:因为类类型的数据成员对象在进入函数体前已经构造完成,也就是说在成员初始化列表处进行构造对象的工作,调用构造函数,在进入函数体之后,进行的是对已经构造好的类对象的赋值,又调用个拷贝赋值操作符才能完成(如果并未提供,则使用编译器提供的默认按成员赋值行为)


2. 那么什么时候需要构造函数初始化列表呢?
(1) const成员
(2) 引用类型成员
(3) 继承类中调用基类初始化构造函数, 实际上就是先构造基类对象, 必须使用初始化列表.
        以上3种情况需要在构造函数初始化列表中对数据成员进行显式初始化。因为const和引用类型成员只能初始化,不能对其进行赋值操作。

事实上我们应该尽量使用初始化列表,而不要在构造函数里赋值

3. 初始化顺序
        构造函数初始化列表只是指定了成员的初始值,并没有指定初始化顺序,那么成员初始化顺序又是怎样的呢?成员的初始化顺序就是定义成员的顺序,第一个定义的成员首先被初始化,然后是第二个等等。



版权声明:本文为博主原创文章,未经博主允许不得转载。

构造函数初始化列表和构造函数体内赋值

标签:cc++

原文地址:http://blog.csdn.net/meetings/article/details/47037305

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!