首先看一道面试题如下:
A test()
{
A a1 (2);
std::cout << &a1 << std::endl;
return a1;
}A a2 = test();
对于以上代码,大概解释下过程。
test()函数中构造a1对象,当返回时,构造临时对象,并使用a进行拷贝构造。当A a2 = test()是,a2使用临时对象进行拷贝构造,也就是一共有2次拷贝构造,1次构造函数;
但是当使用代码测试的时候,结果和想象的不一样。
#include <iostream>
class A
{
public:
A(int i)
:a(i)
{
std::cout << "construct " << i <<std::endl;
}
~A()
{
std::cout << "des constrcut " << a << std::endl;
}
A(const A& a)
{
std::cout << "copy constrcut " << std::endl;
this->a = a.a;
}
A& operator=(const A& b)
{
std::cout << "assign operation " << std::endl;
this->a = b.a;
return *this;
}
public:
int a;
};
A test()
{
A a (2);
std::cout << &a << std::endl;
return a;
}
int main()
{
A a = test();
std::cout << &a << std::endl;
return 0;
}
g++ test.cpp -o test ,运行时,输入如下。
结果发现,构造函数只执行了一次,并且没有执行拷贝构造函数,并且test()函数体内的对象地址和main()中的对象地址竟然相同。
查询后发现,原来编译器会自动执行值返回优化,即RVO。RVO会将a对象的地址传到test函数中,test函数直接修改a对象,避免了拷贝操作。维基百科有详细介绍:http://en.wikipedia.org/wiki/Return_value_optimization。
最后,gnu的编译器可以通过-fno-elide-constructors 选项关闭RVO。g++ test.cpp -fno-elide-constructors -o test。 运行结果如下。
大概过程如下:
test()函数对象a调用构造函数,返回时候临时对象拷贝构造,然后函数内对象析构。
然后main()函数对象a拷贝构造临时对象,然后析构临时对象。
最后析构对象a。
原文链接: https://www.cnblogs.com/jerett/p/4553620.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/217210
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!