c++ - 什么时候需要 R 值引用?

标签 c++ c++11 language-lawyer rvalue-reference

我明白,如果没有 R 值引用,C++ 中的完美转发是不可能的。

但是,我想知道:还有什么需要它们吗?


例如,this page指出这个例子,其中 R 值引用显然是必要的:

  X foo();
  X x;
  // perhaps use x in various ways
  x = foo();

The last line above:

  • Destructs the resource held by x,
  • Clones the resource from the temporary returned by foo,
  • Destructs the temporary and thereby releases its resource.

但是,在我看来,如果正确实现 swap,一个简单的更改就可以解决问题:

X foo();
X x;
// perhaps use x in various ways
{
    X y = foo();
    swap(x, y);
}

所以在我看来,r 值引用不是此优化的必需。 (对吗?)

那么,有哪些问题不能通过 r 值引用解决(完美转发除外,我已经知道了)?

最佳答案

So, what are some problems that could not be solved with r-value references (except for perfect forwarding, about which I already know)?

是的。为了使 swap 技巧发挥作用(或至少发挥最佳作用),类必须设计为在构造时处于空状态。想象一个 vector 实现,它总是保留一些元素,而不是一开始就完全是空的。从这样一个默认构造的 vector 与一个已经存在的 vector 交换将意味着进行额外的分配(在这个 vector 实现的默认构造函数中) .

在实际移动中,默认构造的对象可以分配数据,但移出的对象可能处于未分配状态。

另外,考虑这段代码:

std::unique_ptr<T> make_unique(...) {return std::unique_ptr<T>(new T(...));}

std::unique_ptr<T> unique = make_unique();

如果没有语言级别的移动语义,这是不可能的。为什么?因为第二个说法。按照标准,这是复制初始化。顾名思义,这要求类型是可复制的unique_ptr 的全部意义在于它是独一无二的。 IE:不可复制。

如果移动语义不存在,则无法返回它。哦,是的,您可以谈论复制省略等,但请记住:省略是一种优化。符合规范的编译器仍然必须检测复制构造函数是否存在并且是可调用的;编译器只是可以选择不调用它。

所以不,你不能只用 swap 模拟移动语义。坦率地说,即使可以,您为什么想要

您必须自己编写swap 实现。所以如果你有一个有 6 个成员的类,你的 swap 函数必须依次交换每个成员。递归遍历所有基类等。

C++11(但不是 VC10 或 VC2012)允许编译器为您编写移动构造函数

是的,在某些情况下您可以不用它就可以逃脱。但它们看起来非常老套,很难理解您为什么要那样做,最重要的是,它们给读者和作者都带来了困难。

当人们为了性能而想做很多事情时,这使得他们的代码读起来很乏味,难以编写并且容易出错(在类中添加另一个成员而不将其添加到 swap function,例如),那么你正在寻找的东西可能应该成为语言的一部分。尤其是当它是编译器可以很容易处理的东西时。

关于c++ - 什么时候需要 R 值引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11167630/

相关文章:

c++ - std::is_trivially_copyable 太强了,我应该用什么来代替?

c++ - 错误 : Heap block at X modified

c++ - 用户定义的数字文字可以紧跟一个点吗?

c++ - std::is_trivially_equality_comparable_v<T>

c++ - 使用转换为 "wrong"类型的指针算法

c++ - VS2008 C++ "interface"作为参数名编译失败

c++ - 什么时候重载 operator new?

c++ - 为什么我的 SFINAE 表达式不再适用于 GCC 8.2?

c++ - 是否可以使用互斥锁只锁定数据结构的一个元素?

c++ - 有没有办法在 Visual Studio 2012 中使用委托(delegate)构造函数?