C++构造函数、拷贝构造函数、赋值运算符漫谈(三)——NRV

简介:
//

首先看下面一段程序:

class X
{
public:
	X()
	{
		cout<<"X()"<<endl;
	};
	X(int v):val(v)
	{
		cout<<"X(int)"<<endl;
	}
	X(const X& x)
	{
		cout<<"X(const X& x)"<<endl;
	}
	X& operator=(const X&)
	{
		cout<<"="<<endl;
		return *this;
	}
	~X()
	{cout<<"destructor"<<endl;}
	void memfun()
	{
	  cout<<"memfun"<<endl;
	}
private:
	int val;
};

int _tmain(int argc, _TCHAR* argv[])
{
   X x0(1024);
	X x1=X(1024);
	X x2=(X)1024;
}

以上两个运行结果截图分别来自VSg++

    看到这个输出,相信不少人和我一样有疑惑:为什么没有调用拷贝构造函数?在回答这个疑问之前,我们先解决另外一个疑问——使用“=”创建的对象就一定要调用拷贝构造函数吗?

     从运行结果来看是否定的,在创建x1,x2的时候,我们的预想是编译器先创建一个临时对象,在使用临时对象作为拷贝构造函数的参数创建新对象。其实这里编译器采用了一种优化,叫做Named Return Value(NRV)。

Named Return value 优化:

nrv优化的本质是优化掉拷贝构造函数,去掉它不是生成它。当然了,因为为了优化掉它,前提就是它存在,也就是欲先去之,必先有之,这个也就是nrv优化需要有拷贝构造函数存在的原因。 nrv优化会带来副作用,目前也不是正式标准,倒是那个对象模型上举的应用例子看看比较好。极端情况下,不用它的确造成很大的性能损失,知道这个情况就可以了。  

为什么必须定义了拷贝构造函数才能进行nrv优化?首先它是lippmaninside c++ object mode里说的。那个预先取之,必先有之的说法只是我的思考。查阅资料,实际上这个可能仅仅只是cfont开启NRV优化的一个开关。 

The C++ standard allows the elision of the copy constructor (even if this results in different program behavior), which has a side effect of enabling the compiler to treat both objects as one。也就是我说的副作用,c++标准允许这个副作用的出现,也就是它允许进行NRV优化,但不是必须。 


目录
相关文章
|
2月前
|
编译器 C++
C++ 类构造函数初始化列表
构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。
72 30
|
1月前
|
编译器 C语言 C++
C++入门4——类与对象3-1(构造函数的类型转换和友元详解)
C++入门4——类与对象3-1(构造函数的类型转换和友元详解)
18 1
|
2月前
|
C++
【C++基础】运算符详解
这篇文章详细解释了C++中运算符的用法,包括算术运算符、赋值运算符、比较运算符和逻辑运算符,以及它们在表达式中的作用和示例。
25 2
|
1月前
|
C++
C++构造函数初始化类对象
C++构造函数初始化类对象
16 0
|
1月前
|
C++
C++入门4——类与对象3-2(构造函数的类型转换和友元详解)
C++入门4——类与对象3-2(构造函数的类型转换和友元详解)
20 0
|
23天前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
21 4
|
23天前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
20 4
|
23天前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
17 1
|
1月前
|
存储 编译器 C++
【C++类和对象(下)】——我与C++的不解之缘(五)
【C++类和对象(下)】——我与C++的不解之缘(五)
|
1月前
|
编译器 C++
【C++类和对象(中)】—— 我与C++的不解之缘(四)
【C++类和对象(中)】—— 我与C++的不解之缘(四)