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;
}

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

以上两个运行结果截图分别来自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优化,但不是必须。 


上一篇:C++数据成员


下一篇:3750的访问列表in 与out 的测试