2012-11-27 42 views
9

According to another answer,如果参照它的表达是一个x值表达一个rvalue参考不会延长的临时的寿命。由于std::move返回一个右值引用,调用它的表达是x值,因此在悬挂参考下面的结果:扩展一个临时的寿命与右值参考

int main() 
{ 
    std::string&& danger = std::move(get_string()); // dangling reference ! 
    return 0; 
} 

这很好。 std::move在这里没有意义;它已经是一个右值。

但这里的地方我画一个空白。这与传递xvalue表达式作为参数有什么不同,完全标准的使用std::move和右值引用?

void foo(const std::string& val); 
// More efficient foo for temporaries: 
void foo(std::string&& val); 

int main() 
{ 
    std::string s; 
    foo(std::move(s)); // Give up s for efficiency 
    return 0; 
} 

是否有右值引用参数,将延长临时寿命的特殊规则,不管它是prvalue或x值?或者是std::move调用表达式只是一个xvalue,因为我们传递了一个已经是右值的东西?我不这么认为,因为无论如何它返回一个右值引用,这是一个xvalue。我很困惑。我想我错过了一些愚蠢的东西。

+0

无关:如果函数'foo'是要复制或移动无论哪种方式,您可能希望只取按值参数,让编译器做复制或移动。 –

+0

关于第一个示例的注释:'std :: move(get_string())'不是一个临时表达式。临时表达式是'get_string()',但是然后你施放它。因此,关于临时表达式绑定到引用的规则不再适用。 –

回答

7

此处没有必要延长任何生命周期:所讨论的对象持续到main的末尾,这是foo的末尾之后。

+0

的确......在给定的代码中甚至没有任何临时对象。 – Mankarse

+4

哦,我的天啊。我需要睡眠。 –

8

第二个示例没有将临时引用传递给它,它将一个引用传递给变量s,该变量持续到main()的末尾。

如果它是(例如foo(std::move(get_string()));),则临时的寿命持续,直到充分表达的端部 - 该函数返回之后。因此在foo内使用它非常安全。如果foo存储引用/指向其参数的唯一危险,并且稍后尝试使用它。

+1

但rvalues地址是非法的。 – user1095108

+4

@ user1095108但'val'不是功能'FOO(的std :: string && VAL)'的主体内的右值。这是一个左值类型的“右值参考”。完全合法的地址,并使用它的地址,直到's'的寿命结束。 – Oktalist