为啥 const rvalue 限定 std::optional::value() 返回 const rvalue 引用?

Posted

技术标签:

【中文标题】为啥 const rvalue 限定 std::optional::value() 返回 const rvalue 引用?【英文标题】:Why does the const rvalue qualified std::optional::value() return a const rvalue reference?为什么 const rvalue 限定 std::optional::value() 返回 const rvalue 引用? 【发布时间】:2017-10-31 15:05:59 【问题描述】:

std::optional::value() 有以下两个重载

constexpr T& value() &;
constexpr const T & value() const &; 
constexpr T&& value() &&;
constexpr const T&& value() const &&;

返回 const 右值引用有什么意义?

我能想到的唯一原因是让编译器能够在以下(真的很奇怪)情况下帮助捕捉未定义的行为

auto r = std::cref(const_cast<const std::optional<int>&&>(
    std::optional<int>).value());

如果std::optional::value() 返回了const T&amp;,那么上面的代码将编译并在稍后使用r reference_wrapper 时导致未定义的行为。

上述返回const T&amp;&amp; 是否有任何其他极端情况?

【问题讨论】:

不能相信其他人的知识,但这里有一个链接:nirfriedman.com/2016/01/18/… 在“可选的安全迭代”部分中,有一些关于在何处使用 T&amp;&amp; value() 的有用信息。跨度> 返回对 const 对象的非常量引用是不安全的……返回对可能是临时对象的左值引用也是不安全的……所以,它返回一个 const右值引用 您建议的替代方案是什么?非const 右值引用? const 左值引用? 我想知道为什么他们需要添加这个重载而不是只添加一个const T&amp; 重载。如果他们需要,为什么不直接返回const T&amp;?这种重载有一些实际用例吗? this 可能重复?归根结底,这个问题只是:T const&amp;&amp; 的意义何在。 【参考方案1】:

当然。你在结构中有一个const optional&lt;T&gt;。您返回一个右值实例并访问可选成员。

由于您构建它的方式,您可以保证在这种情况下使用可选。所以你打电话给value()T 类型包含 mutable 状态,可以有效地重用/窃取。 T const&amp;&amp; 重载赋予消费函数窃取该状态的权限。

struct mutable_type 
  mutable std::vector<char> cache;
;
struct test_type 
  const std::optional<mutable_type> bob;
;
test_type factory( int x ) 
  if (x==0) return ;
  return mutable_type(1,2,x);


auto moved_into = factory(3).bob.value().cache;

我相信,这会将vector 移动到bob 中,在这种情况下这是一个const 右值。它依赖于value()const&amp;&amp; 上下文中返回const&amp;&amp;

【讨论】:

const T&amp;&amp; 重载如何授予函数窃取其状态的权限?我不认为我遵循... @curious 在这种情况下状态是可变的,因此 const 不会阻止任何内容。 &amp;&amp; 表示该对象是一个右值或被强制转换为一个右值,因此调用者保证不会介意您窃取某些状态。 你能举例说明你的意思吗? @Curious 玩具示例已添加。 即使value() 方法返回了const&amp;,这个例子也不能工作吗?

以上是关于为啥 const rvalue 限定 std::optional::value() 返回 const rvalue 引用?的主要内容,如果未能解决你的问题,请参考以下文章

为啥允许我在 C 中使用 const 限定变量作为数组大小?

为啥 const 限定变量被接受为 gcc 上的初始化程序?

返回 const 引用和 rvalue 引用之间的区别

为 const 引用和 rvalue 引用编写重载

C++,在函数中采用 const lvalue 和 rvalue 引用

const rvalue 编译器的区别