On this link,Howard Hinnant先生展示了以下代码:
#include <utility>
#include <cassert>
struct A
{
A() : data_(1) {}
A(A&& a) : data_(a.data_) {a.data_ = 0;}
int data_;
};
void g(const A&) {}
void g(A&& a) {a.data_ = 0;}
void h(const A&) {}
void h(A&& a) {a.data_ = 0;}
void f(A&& a)
{
g(a); // calls g(const A&)
h(a); // calls h(const A&)
if (true)
{
h(a); // calls h(A&&) (by Alexandrescu rules)
}
}
int main()
{
A a;
f(a);
assert(a.data_ == 1);
}
然后他写道:
根据N1377规则,它没有断言。 ...
使用实际的C ++ 11规则,上面的代码无法编译,因为a
中的左值main()
未绑定到右值引用。但是,只是假设它被编译,正如本次讨论发生的情况可能应该这样,我无法理解上面的断言,即By the N1377 rules, it does not assert.
。根据先前的规则,变量a
不会被盗(a.data_ = 0),因为a
作为参数传递给f
f(a)?
答案 0 :(得分:1)
在C ++ 0x标准中,&amp;&amp;声明专门提到r值参考。评论中的链接以及此链接引用了2006版本。
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2118.html
你也可以深入讨论这个问题,以及为什么它在这里很重要:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2027.html
简而言之,右值引用消除了对以下习语的需要:
int a = 10;
int b = 1000;
//Now let's swap them
int temp = a;
a = b;
b = temp;
rvalue引用允许不涉及创建临时对象的惯用语,并使用50%以上的内存。尽管如此,即使按照我们关心A&amp; A之间差异的旧标准来说也是如此。和A&amp;&amp;,如果你编写合理的代码,使用rvalue引用dissapears,因为任何体面的编译器都可以在标准代码中轻松优化其优势。
老实说,我不知道为什么h(a)调用会改变为rvalue引用,因为它是在if语句的范围内调用的。
编辑:根据评论。
有人提出,变量范围内变量的最终使用应该默认为rvalue版本,因为这是更优化的,并且这种引用可能导致的盗窃无关紧要,因为变量很快就会超出范围。
所以,const A&amp;版本比A&amp;&amp;版。尽管const A&amp;是一种更简洁的类型匹配,A&amp;&amp;版本更快,并且使用它的危险对于左值的最后引用是不存在的。 Alexandrescu建议,对于这样的“最终参考”,我们使用rvalue。
然而,Hinnant声明(通过评论),在Alexandrescu建议的修改下,代码没有按预期执行并且抛出断言,但根据当前的n1377规则,使用标准绑定,它不会。揭穿他提议的标准变更。