2011-07-28 44 views
3

只是一定要很好地理解什么是引擎盖下...问题是在代码中评论移动语义和变量终身绑定时左值右值来引用

void test(int && val) 
    { 
     val=4; 
    }//val is destroyed here ? 

int main() 
{ 
    int nb; 
    test(std::move(nb)); 
    //undefined behavior if I reference here nb ? 
    std::cout << nb; 
    nb=5; 
    std::cin.ignore();  
} 
+1

'void main()'... –

回答

3

移动的值保留在有效但未指定的状态。就我所知,这基本上意味着它可能包含任何值,但它必须包含一些值,并且访问它是合法的和已定义的行为。

1

这不是不确定的行为,因为你从来没有实际从val移动到你的函数中。 std::move仅仅将nb变成右值。这实际上只有在你有其他模糊的test过载时才有意义。

0
//val is destroy here ? 

相同的答案,如果参数类型是const int& val

//undefined behavior if I reference here nb ? 

号但是没有指定打印出来的值。这不同于“未定义的行为”,这意味着任何事情都可能发生。如果它是未定义的行为将意味着您的磁盘可能会被重新格式化。

+2

你能解释为什么在这种情况下未指定打印值吗?我会预料它会被详细说明,因为在函数内部没有实际的移动操作。 –

+2

我相信这种行为的确有明确的规定;它将'nb'设置为4。不过,我可能错了,所以你可以澄清为什么它会有一个不明确的价值? – templatetypedef

+0

我明显地解释了这个问题。如果您不执行整个程序分析,则未指定要移动的对象的值。在这种情况下,我特意在分析'main'时忽略了'test()'的定义。 –

3

你必须明白,右值对某物的引用不会神奇地移动该值。它所做的只是使得可以对临时对象进行非const引用。

此参考在您的示例中与正常参考没有区别,因为您在此处没有任何临时对象。你是必须让“行动”发生的人。

E.g.如果你定义你的int值为0,那么你的int就是空的,并且你编写了一个接受右值引用的函数,将它消耗并将传递值设置为0,那么你将前面的值“移出”你的int值。调用此函数后,它将包含0。但那是因为这样定义它。

现在,对于整数来说这没什么意义,但想象你正在处理一个指向大块内存的指针。

+0

“你必须明白,某个参数的参数不会神奇地移动该值”,的确如此 – Guillaume07

+0

@Guillaume我很抱歉如果我低估了你的专业知识,但是你的问题“val在这里被摧毁了吗?对我来说没有多大意义。 Val是一个引用,所以是的,引用val在那个时候被销毁,但是val引用的变量继续存在,直到它超出变量的作用域或直到它为临时对象创建的表达式的“;” 。 – Fozi

0

有关std :: move的详细说明,请参阅here。除非你没有开始使用移动构造函数,否则你将无法有效地使用这个新功能。另外,我认为对于没有开销的基本类型来说它没有任何意义。