Copy Elision
C++11/14/17编译器优化:省略不必要的拷贝
- 至少包括以下两项内容:
- 返回值优化(RVO),即通过将返回值所占空间的分配地点从被调用端转移至调用端的手段来避免拷贝操作。
- 返回值优化包括具名返回值优化(NRVO)与无名返回值优化(URVO),两者的区别在于返回值是具名的局部变量还是无名的临时对象。
- 右值拷贝优化,当某一个类类型的临时对象被拷贝赋予同一类型的另一个对象时,通过直接利用该临时对象的方法来避免拷贝操作。
- 这项优化只能用于右值(临时对象),不能用于左值。
- 返回值优化(RVO),即通过将返回值所占空间的分配地点从被调用端转移至调用端的手段来避免拷贝操作。
#include <iostream>
#include <vector>
struct Noisy {
Noisy() { std::cout << "constructed\n"; }
Noisy(const Noisy&) { std::cout << "copy-constructed\n"; }
Noisy(Noisy&&) { std::cout << "move-constructed\n"; }
~Noisy() { std::cout << "destructed\n"; }
};
std::vector<Noisy> f() {
std::vector<Noisy> v = std::vector<Noisy>(3); // copy elision when initializing v
// from a temporary (until C++17)
// from a prvalue (since C++17)
return v; // NRVO具名传回值最佳化(Named Return Value Optimization) from v to the result object (not guaranteed, even in C++17)
} // if optimization is disabled, the move constructor is called
void g(std::vector<Noisy> arg) {
std::cout << "arg.size() = " << arg.size() << '\n';
}
int main() {
std::vector<Noisy> v = f(); // copy elision in initialization of v
// from the temporary returned by f() (until C++17)
// from the prvalue f() (since C++17)
g(f()); // copy elision in initialization of the parameter of g()
// from the temporary returned by f() (until C++17)
// from the prvalue f() (since C++17)
Possible result:
constructed
constructed
constructed
constructed
constructed
constructed
arg.size() = 3
destructed
destructed
destructed
destructed
destructed
destructed