【问题标题】:Use of rvalue reference members?使用右值引用成员?
【发布时间】:2011-06-14 01:12:30
【问题描述】:

我想知道右值引用成员有什么用

class A {
  // ...
  // Is this one useful?
  Foo &&f;
};

与左值引用成员相比,它有什么优点或缺点吗?它的主要用例是什么?

【问题讨论】:

  • @GMan 我不知道为什么这比说template<typename T> struct acw { T &t; acw(T &&t):t(t) {} template <typename U> operator U() { return static_cast<U>(std::forward<T>(t)); } } 更好。通过让成员 t 成为右值引用,您可以获得什么?顺便说一句,我认为 n3225 表示如果您有任何右值引用成员,则默认的复制构造函数被定义为已删除。所以你仍然不能复制auto_cast_wrapper<nonlref>,只能移动它:)
  • 没什么,我只是说我用过,哈哈。嗯,很高兴知道。稍后我将不得不修复它。
  • @GMan 哦,我现在明白了!感谢您的展示,我认为这是一些有趣的工具。

标签: c++ c++11 rvalue-reference


【解决方案1】:

根据Stephan T. Lavavej,右值引用数据成员没有用。

[at 31:00] 我看到程序员在获得右值引用时会做的事情是,他们开始有点疯狂,因为他们太强大了。他们开始说“哦,我将拥有 右值引用数据成员,我将拥有右值引用局部变量,我将拥有右值引用返回值!”然后他们编写这样的代码:[...]

【讨论】:

  • 我们大约需要 10 年才能弄清楚如何正确使用右值引用。
  • @7vies:程序员对右值引用感到困惑的主要原因是他们已经对右值感到困惑。
  • @Martin:没错,十年后 C++ 委员会即将发布 C++2x,它可能会有一些全新的表达方式,我们必须学习。 . ξvalues,也许。
  • @James:我当然希望如此。永远只停留在五个不同的价值类别上会有点无聊,不是吗?
  • 谁可能想知道,他在视频中 31:00 这么说。
【解决方案2】:

我看到了一个非常鼓舞人心的右值引用数据成员用例,它在 C++0x 草案中:

template<class... Types>
tuple<Types&&...>
forward_as_tuple(Types&&... t) noexcept;

效果:构造一个元组 对 t 中的参数的引用 适合作为参数转发 到一个函数。因为结果可能 包含对临时的引用 变量,程序应确保 这个函数的返回值 不会超过它的任何论点。 (例如,程序通常应该 不将结果存储在命名的 变量)。

返回:tuple&lt;Types&amp;&amp;...&gt;(std::forward&lt;Types&gt;(t)...)

当右值用作 forward_as_tuple 的参数时,元组具有右值引用数据成员,否则具有左值引用数据成员。

我发现 forward_as_tuple 随后在需要捕获可变参数时很有帮助,将它们完美地打包为一个元组,并在稍后转发到函子时重新展开它们。在实现 LWG 1385 中提出的 tuple_cat 的增强版本时,我使用了这种风格的 forward_as_tuple:

http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#1385

【讨论】:

  • 您能解释一下在这种情况下如何管理右值生命周期吗?右值破坏是否以某种方式延长到使用右值的“稍后”点?
  • 感谢您的回答和解释。问题提出了什么要求“因为结果可能包含对临时变量的引用,程序应确保此函数的返回值不会超过它的任何参数。”暗示一个程序。像这样的 sn-p 是否有未定义的行为? { auto x = forward_as_tuple(0); },因为它违反了效果部分的应要求?为什么需要这样的要求?是否不允许破坏包含陈旧引用的元组?
  • forward_as_tuple 的客户端必须保证结果在序列点之前被“消费”。它的第一个使用示例位于:open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3059.pdf,但在本文档中,该函数被称为 pack_arguments 而不是 forward_as_tuple。 N3059 中的使用显示了引用元组的创建、传递给另一个函数、消耗(使用)和销毁的顺序。
【解决方案3】:
class A {
  // ...
  // Is this one useful?
  Foo &&f; 
};

在这种特定情况下,没有理由使用右值引用。它不会给你买任何你以前做不到的东西。

但您可能希望使用参数化类型定义数据成员。例如,std::tuple 将支持左值和右值引用数据成员。通过这种方式,它允许您编码表达式的值类别,这对于“延迟完美转发”可能会派上用场。标准草案甚至包括表单的功能模板

template<class Args...>
tuple<Args&&...> pack_arguments(Args&&...args);

但老实说,我不确定它的用处。

【讨论】:

【解决方案4】:

只是在这里大声思考,但它在函子中没有用吗?构造函数常用于“柯里化”,在实际函数调用之前预先绑定一些参数。

因此,在这种情况下,类成员只是即将到来的函数调用的暂存地(或手动实现的闭包),我认为右值引用在那里没有意义。

但在“常规”非函子类中,我认为没有什么意义。

【讨论】:

  • 在这种情况下,右值引用如何优于const &amp;(或者如果您需要修改它,则只是普通引用)?
  • 出于同样的原因,您可能希望将右值 ref 传递给函数:以便能够从中移动
  • @jalf:那么就按值传递,从参数移动到成员。
  • @Fred:大概整个要点是避免必须按值传递(也许参数类型不可复制,但它可能是可移动的)
  • @jalf:我不确定我明白你的意思。如果参数是右值,则按值传递意味着移动。 Related FAQ entry
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-25
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 2023-03-04
  • 2016-06-10
相关资源
最近更新 更多