首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么C++不对std::可选执行RVO?

为什么C++不对std::可选执行RVO?
EN

Stack Overflow用户
提问于 2022-11-16 11:10:30
回答 2查看 87关注 0票数 1

我想知道为什么C++在返回T时不对std::optional<T>执行RVO。也就是说,

代码语言:javascript
复制
struct Bar {};
std::optional<Bar> get_bar()
{
    return Bar{}; // move ctor of Bar called here
                  // instead of performing RVO
}
Bar get_bar2()
{
    return Bar{}; // NO move ctor called
                  // RVO performed
}
std::optional<Bar> get_bar_rvo()
{
    std::optional<Bar> opt;
    opt.emplace();
    return opt;  // NO move ctor called
                 // ROV performed
}

在上述情况下,get_bar2执行RVO,而get_bar不执行RVO。

使用更多的提示,编译器能够优化get_bar_rvo,但是代码会变得更长、更烦人。

参考文献中,我了解到get_bar不符合“强制复制/移动操作”的要求。

在对象的初始化中,当初始化器表达式是与变量类型相同的类类型(忽略cv限定)的prvalue时:

因为std::optional<T>T不是相同的类类型,所以RVO不是强制性的。

但是,我认为对std::optional<T>执行RVO应该非常容易,而且非常有用,不需要手动将较长的代码编写为get_bar_rvo

为什么我的编译不能像get_bar一样识别和优化get_bar2

环境: MacOS

代码语言:javascript
复制
Apple clang version 13.1.6 (clang-1316.0.21.2.5)
Target: arm64-apple-darwin21.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

-std=c++17 -O3编译

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-11-16 11:56:31

get_bar_rvo不执行RVO,它执行NRVO (称为返回值优化)。这不能保证。

对于get_bar,与其自己构建Bar,不如使用std::make_optional它的就地构造函数(6)将其留给std::optional

代码语言:javascript
复制
std::optional<Bar> get_bar()
{
    return std::make_optional<Bar>();
    // or return std::optional<Bar>(std::in_place);
}

这将像预期的那样执行RVO。

票数 3
EN

Stack Overflow用户

发布于 2022-11-16 12:22:11

get_bar()返回std::optional<Bar>,并且不会像预期的那样复制或移动std::optional<Bar>

Bar被移动到std::optional<Bar>,因为您创建了一个临时Bar,然后请求从它构建std::optional<Bar>。与RVO或NRVO无关。它是关于将对象传递给函数的。

我们不期望在像foo(Bar{})这样的旧函数调用中消除移动,std::optional构造函数也不例外。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74459462

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档