c++ - 如何确保执行 RVO 而不是复制?
问题描述
在许多情况下,我想创建一个新的数据实例并将其返回给 API 调用者。
我了解到unique_ptr
/shared_ptr
可用于工厂模式(例如,工厂模式 using unique_ptr in c++)
同时,我了解到返回值优化 (RVO) 在许多编译器中都是可能的(例如,Efficient way to return a std::vector in c++)。
我更喜欢 RVO,因为它更容易使用没有包装的返回值unique_ptr
并且更容易阅读代码,但是,由于 RVO 没有保证,我不想意外牺牲性能并且必须使用unique_ptr
来确保返回值是move
d而不是复制。
是否有任何方法可以明确指定要移动的返回值,以便如果 RVO 可能它不会抱怨任何事情,或者如果 RVO 不可能它会触发一些编译器警告?如果这是可能的,我可以安全地摆脱在这种情况下返回 unique_ptr 。
我正在使用 C++17,需要在 macOS 上支持 Apple Clang 11.0,在 Linux 上支持 g++ 9。
编辑:
我仍在学习 C++,并且在发布此问题时没有区分 RVO(返回值优化)和 NRVO(命名返回值优化)。在我看来,NRVO 在工厂方法等模式中更常见和有用,例如:
vector<foo> vec;
// populate data into vec
return vec;
我正在寻找类似的东西return std::move_only(returned_value)
,如果这个值不能移动(而不是复制移动),它会给我一个编译器警告。也许我应该将我的问题重新表述为:如果不能保证 NRVO,为什么在这个问题中“按值返回”仍然是推荐的方式(在 c++ 中返回 std::vector 的有效方式),答案不应该是“这取决于”您的功能实现以及您是否可以接受意外的性能成本?
解决方案
如何确保执行 RVO 而不是复制?
从 C++17 开始,该语言已经为您完成了这项工作。如果你有一个像
T foo() { /*stuff*/; return T{ /*stuff*/ }; }
然后,由于保证复制省略,可以保证省略返回的对象。
如果你有一个像
T foo()
{
T obj{ /*stuff*/ };
// do stuff with obj
return obj;
}
然后你会得到 NRVO(命名返回值优化),这是不保证的,或者编译器会移动obj
,因为标准中有一条规则,所有具有自动存储持续时间的函数本地对象都将被移出函数,如果它们有移动构造函数。
这意味着您获得副本的唯一时间是如果您返回一个无法优化的对象(它是命名的本地对象或函数参数)并且它不支持移动。全局对象总是被复制,因为它们没有作用于函数。
推荐阅读
- java - 获得第 n 个 nextInt 值的最快方法是什么?
- scorm - 将 Scorm 的课程位置转换为其 xAPI 等效项
- java - 从服务器下载文件时,Android 改造响应返回内部服务器错误
- numpy - 如何在python keras中计算张量上浮点数的熵
- javascript - 后台脚本不会在扩展的生命周期内持续存在
- css - 使用 R 的没有提交按钮的网页抓取弹出表
- exception - 使用指向我的函数的指针 arg 会引发异常
- java - 无法为我本学期的最后一个实验室正确读取文件,并且在读取实际文件时遇到问题
- javascript - 每 10 毫秒重复一次 ajax 会减慢同一页面中其他 ajax 调用的加载速度
- html - 如何更改表单的输入背景颜色?