c++ - 如何确保执行 RVO 而不是复制?

标签 c++ smart-pointers nrvo

在许多情况下,我想创建一个新的数据实例并将其返回给 API 调用方。

我了解到 unique_ptr/shared_ptr 可用于工厂模式(例如, Factory pattern using unique_ptr in c++ )

同时,我了解到在许多编译器(例如 Efficient way to return a std::vector in c++ )中都可以进行返回值优化 (RVO)。

我更喜欢 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,为什么“按值返回”仍然是这个问题( Efficient way to return a std::vector in c++ )中的推荐方式,答案不应该是“取决于”你的函数实现以及是否你能不能接受意外的性能成本?

最佳答案

How can I ensure RVO instead of copy is performed?


从 C++17 开始,该语言已经为您做到了这一点。如果你有一个像
T foo() { /*stuff*/; return T{ /*stuff*/ }; }
由于 guaranteed copy elision,返回的对象保证被忽略。 .
如果你有一个像
T foo() 
{
    T obj{ /*stuff*/ }; 
    // do stuff with obj
    return obj;
}
然后你要么得到不保证的 NRVO(命名返回值优化),要么编译器将移动 obj因为标准中有一个规则,所有具有自动存储持续时间的函数本地对象,如果它们有移动构造函数,就会被移出函数。
这意味着唯一一次你会得到一个拷贝是如果你返回一个不能优化的对象(它是一个命名的本地或者它是一个函数参数)它不支持移动。全局对象总是被复制,因为它们不限于函数。

关于c++ - 如何确保执行 RVO 而不是复制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60546268/

相关文章:

c++ - boost 的 shared_ptr(shared_ptr<Y> const & r, T * p) 是做什么用的?

c++ - RVO 是否与 "new"一起使用?

c++ - 我在哪里定义代码来释放在 C Python 模块 init 函数中分配的资源?

c++ - 将 FFmpeg 与 Direct Show 结合使用

c++ - 制作时钟/计时器类时出现异常错误

c++ - DirectX、引用计数和智能指针

c++ - C++ 中的读写线程安全智能指针,x86-64

c++ - 为什么要依赖命名返回值优化?

c++ - 为什么下面的代码也会调用拷贝构造函数呢?

c++ - 缺少 cmake 的 sfml 库