什么是复制省略?什么是(命名的)返回值优化?它们意味着什么?
在什么情况下会发生?什么是限制?
简介
技术概览 - skip to this answer .
对于发生复制省略的常见情况 - skip to this answer .
复制省略是大多数编译器实现的一种优化,用于在某些情况下防止额外的(可能是昂贵的)复制。它使按值返回或按值传递在实践中可行(有限制)。
这是省略(哈哈!)as-if 规则的唯一优化形式 - 即使复制/移动对象有副作用,也可以应用复制省略。
以下示例取自 Wikipedia :
struct C {
C() {}
C(const C&) { std::cout << "A copy was made.\n"; }
};
C f() {
return C();
}
int main() {
std::cout << "Hello World!\n";
C obj = f();
}
根据编译器和设置,以下输出都是有效的:
Hello World!
A copy was made.
A copy was made.
Hello World!
A copy was made.
Hello World!
这也意味着可以创建更少的对象,因此您也不能依赖于调用特定数量的析构函数。您不应该在复制/移动构造函数或析构函数中包含关键逻辑,因为您不能依赖它们被调用。
如果省略了对复制或移动构造函数的调用,则该构造函数必须仍然存在并且必须是可访问的。这确保了复制省略不允许复制通常不可复制的对象,例如因为他们有一个私有(private)的或已删除的复制/移动构造函数。
C++17:从 C++17 开始,直接返回对象时保证复制省略:
struct C {
C() {}
C(const C&) { std::cout << "A copy was made.\n"; }
};
C f() {
return C(); //Definitely performs copy elision
}
C g() {
C c;
return c; //Maybe performs copy elision
}
int main() {
std::cout << "Hello World!\n";
C obj = f(); //Copy constructor isn't called
}
我是一名优秀的程序员,十分优秀!