读书人

用一个暂时对象初始化一个新构造的对象

发布时间: 2013-08-13 16:43:28 作者: rapoo

用一个临时对象初始化一个新构造的对象会不会调用复制函数?
用一个临时对象初始化一个新构造的对象会不会调用复制函数?比如说:
A a=A();
什么时候会调用复制构造函数,什么时候不会?

[解决办法]

引用:
将一个函数返回的临时对象赋给一个新对象, 如:
A a=f(); //f会返回一个类A的临时对象
为什么VC中显示调用的是复制构造函数,而在G++中显示调用的是构造函数呢?


请查阅NRVO优化。

对于A a = A(); 或A a = b; 之类的初始化,在抽象语义上,是先调用默认构造函数构造出一个临时A对象,然后运行复制构造函数通过这个临时A对象构造a,就是说,在抽象语义层次,复制构造函数是必然发生的;

但是,对于实现语义,出于提高性能的考虑,C++标准允许一个实现直接在a上构造A()或者A(b),从而省掉一次复制构造函数,提高了性能,这个称为NRVO优化,是常用的优化,现在的编译器一般都带有这个优化,只要自定义了复制构造函数,NRVO优化就会有可能被编译器自动采用。

但是,要注意复制构造函数带来的side effect,当使用NRVO时,最好不要让复制构造函数带有其它副作用,否则这个副作用会同时被编译器忽略,这可能会产生与预期不相同的结果。
[解决办法]
在项目名称上右键->build option->other options中输入。

g++使用-fno-elide-constructors就可以关掉NRVO了。但VS2012和VS2010似乎关不掉的,/Od和/Za都没关掉。
[解决办法]
优化后
cat main.cpp;  g++ main.cpp  -O3 -o demo.exe; ./demo.exe

#include <cstdio>
using namespace std;
class RVO
{
public:

RVO(){printf("I am in constructor @ %p\n", this);}
RVO (const RVO& c_RVO) {
printf ("I am in copy constructor src @ %p this@ %p\n", &c_RVO, this);
}
~RVO(){printf ("I am in destructor @%p\n", this);}
int mem_var;
};

RVO MyMethod (int i)
{
RVO rvo;
rvo.mem_var = i;
return (rvo);
}
int main()
{
RVO rvo=MyMethod(5);
printf("rvo @ %p\n", &rvo);
return 0;


}
/*
I am in constructor @ 0022FF0C
rvo @ 0022FF0C
I am in destructor @0022FF0C
*/

读书人网 >C++

热点推荐