C++11: 拷贝消除与返回值优化(RVO)
·
1. 介绍
拷贝消除和返回值优化其实并不是一个统一的标准的行为,
主要还是看编译器自身的行为和相应的C++版本。
了解这一点的目的主要是要明白,编译器会做出的行为。
2. 举例
直接上代码分析
#include <iostream>
#include <vector>
class Foo {
public:
Foo() = default;
Foo(const Foo &a) {
std::cout << "copy constructor" << '\n';
}
void operator=(const Foo &a) {
if ( this != &a) {
std::cout << "assign op\n";
}
}
};
Foo rvo()
{
return Foo{};
}
Foo nrvo()
{
Foo s{};
return s;
}
// disable copy ellision
// -fno-elide-constructors
// g++ -fno-elid-constructors -O0 -std=c++11
int main()
{
std::cout << "init f1\n";
Foo f1 { rvo() };
std::cout << "init f2\n";
Foo f2{ nrvo() };
return 0;
}
如果我们不考虑任何的拷贝优化,
这个程序会调用四次copy constructor。
对于每个对象来说都是两次拷贝:
第一次是从函数的局部变量到返回值,
第二次是从返回值再到变量的构造。
对于f1来说,第一次拷贝发生在rvo()返回main;
第二次拷贝发生在rvo()的返回值去初始化f1。
对于f2来说,第一次拷贝发生在nrvo返加值s到main;
第二次拷贝发生在用nrvo()的返回值去初始化f2。
而在开启优化后,gcc可以将这四次拷贝全都优化掉!!!
msvc在禁用优化选项开启时,也就是/Od选项,可以优化掉
三次拷贝,猜测是有名对象返回值那次拷贝没有优化掉。
当开启优化选项时,四次拷贝也全都被优化掉了。
gcc可以通过-fno-elide-constructos来禁用掉优化,
从而观察未优化前的拷贝次数。
3. 参考
更多推荐
所有评论(0)