什么是复制省略?什么是(命名的)返回值优化?它们意味着什么?
它们会在什么情况下发生?什么是限制?
- 如果您被提及此问题,您可能正在寻找 介绍。
- 有关技术概述,请参阅 标准参考。
- 在此处查看 常见案例。
原文由 Luchian Grigore 发布,翻译遵循 CC BY-SA 4.0 许可协议
什么是复制省略?什么是(命名的)返回值优化?它们意味着什么?
它们会在什么情况下发生?什么是限制?
原文由 Luchian Grigore 发布,翻译遵循 CC BY-SA 4.0 许可协议
对于技术概述 - 跳到这个答案。
对于技术含量较低的观点和介绍 - 跳到这个答案。
(命名)返回值优化是复制省略的一种常见形式。它指的是从方法中通过值返回的对象的副本被删除的情况。标准中提出的示例说明了 命名返回值优化,因为对象是命名的。
class Thing {
public:
Thing();
~Thing();
Thing(const Thing&);
};
Thing f() {
Thing t;
return t;
}
Thing t2 = f();
返回临时值时会发生常规 返回值优化:
class Thing {
public:
Thing();
~Thing();
Thing(const Thing&);
};
Thing f() {
return Thing();
}
Thing t2 = f();
发生复制省略的其他常见位置是 从临时构造 对象时:
class Thing {
public:
Thing();
~Thing();
Thing(const Thing&);
};
void foo(Thing t);
Thing t2 = Thing();
Thing t3 = Thing(Thing()); // two rounds of elision
foo(Thing()); // parameter constructed from temporary
或者当 异常被抛出并被 value 捕获时:
struct Thing{
Thing();
Thing(const Thing&);
};
void foo() {
Thing c;
throw c;
}
int main() {
try {
foo();
}
catch(Thing c) {
}
}
大多数商业级编译器支持复制省略和 (N)RVO(取决于优化设置)。 C++17 强制要求上述许多复制省略类。
原文由 Luchian Grigore 发布,翻译遵循 CC BY-SA 4.0 许可协议
3 回答2k 阅读✓ 已解决
2 回答3.9k 阅读✓ 已解决
2 回答3.2k 阅读✓ 已解决
1 回答3.2k 阅读✓ 已解决
1 回答2.7k 阅读✓ 已解决
3 回答3.4k 阅读
1 回答1.6k 阅读✓ 已解决
介绍
对于技术概述 - 跳到这个答案。
对于发生复制省略的常见情况,请 跳至此答案。
复制省略是大多数编译器实现的一种优化,用于在某些情况下防止额外的(可能是昂贵的)复制。它使按值返回或按值传递在实践中可行(有限制)。
这是省略(哈哈!)as-if 规则的唯一优化形式 - 即使复制/移动对象有副作用,也可以应用复制省略。
以下示例取自 维基百科:
根据编译器和设置,以下输出 都是有效 的:
这也意味着可以创建更少的对象,因此您也不能依赖于调用特定数量的析构函数。您不应该在复制/移动构造函数或析构函数中包含关键逻辑,因为您不能依赖它们被调用。
如果省略了对复制或移动构造函数的调用,则该构造函数必须仍然存在并且必须是可访问的。这确保复制省略不允许复制通常不可复制的对象,例如因为它们具有私有或已删除的复制/移动构造函数。
C++17 :从 C++17 开始,直接返回对象时保证复制省略: