据我所知,如果没有R值引用,C ++中的完美转发是不可能的。
但是,我想知道:还有什么需要吗?
例如,this page指出了这个示例,其中显然需要R值引用:
X foo(); X x; // perhaps use x in various ways x = foo();
上一行:
- 销毁
所持有的资源x
,- 从
返回的临时值中克隆资源foo
,- 销毁临时用户,从而释放其资源。
但是,在我看来,如果正确实施swap
,那么简单的更改就可以解决问题:
X foo();
X x;
// perhaps use x in various ways
{
X y = foo();
swap(x, y);
}
所以在我看来,r值不会引用必要进行此优化。 (这是正确的吗?)
那么,有什么问题可以不用r值引用解决(除了完全转发,我已经知道了)?
答案 0 :(得分:12)
那么,r值引用无法解决的问题是什么(完全转发除外,我已经知道了)?
是。为了使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();
这是不可能没有语言级别的移动语义。为什么?因为第二个声明。按照标准,这是复制初始化。顾名思义,这需要类型 copyable 。 unique_ptr
的全部意义在于它是独一无二的。 IE:不可复制。
如果移动语义不存在,则无法返回。哦,是的,你可以谈论复制elision等,但请记住:elision是优化。符合标准的编译器仍必须检测到复制构造函数存在且可调用;编译器只能选择不调用它。
所以不,你不能只用swap
来模拟移动语义。而且坦率地说,即使你可以,为什么你会想要?
您必须自己编写swap
个实现。因此,如果您有一个包含6个成员的课程,您的swap
函数必须依次交换每个成员。递归遍历所有基类等。
C ++ 11(虽然不是VC10或VC2012)允许编译器为您编写移动构造函数。
是的,有些情况下你可以在没有它的情况下离开。但他们看起来非常难以理解,很难理解为什么你这样做,最重要的是,让读者和作者都感到困难。
当人们为了性能而想要做很多事情时,会使他们的代码读取繁琐,难以编写和易于维护(在不将其添加到swap
函数的情况下将其他成员添加到类中,例如),那么你正在寻找可能应该成为语言一部分的东西。特别是当编译器可以很容易地处理它时。