lvalue & rvalue
https://www.youtube.com/watch?v=UTUdhjzws5g
作者:知乎用户
链接:https://www.zhihu.com/question/50652989/answer/312543073
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
链接:https://www.zhihu.com/question/50652989/answer/312543073
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
str5被std::move
之后,只是返回了一个它的右值引用。
std::move(str5)
等价于
static_cast<std::string&&>(str5)
如果不去使用这个返回值去触发一下移动的操作,比如用于调用移动构造函数,或者接收右值引用参数的函数,那么原对象是没有任何变化的。
再者,即使进行了这些操作,后续对被move的对象操作也未必一定是undefined的
比如对于STL容器来说,move之后的赋值运算符、clear()都是安全的,但size() push()的行为就是undefined
1.
你的代码中,move()将str5转换成了一个右值引用返回,然后只是又定义了有名字的右值引用rr5并绑定上去。没有触发移动构造函数,因此原对象仍然有效。如果改成std::string rr5 = std::move(str5);
就会触发移动构造函数,因为这是在构造一个新对象,而不是定义一个已有对象的新引用。
2.
由1.可知,str5其实没有改变,而lr5和rr5都是str5的引用(区别只是类型,一个左值引用,一个是右值引用)。他们三个其实指向了同一块空间。因此对他们的更改其实都是对同一个对象的更改。
另外值得注意的一点,右值应该是不能被赋值的,然而为何能够对右值引用类型的rr5赋值? rr5[0] = 'b'
根据左值规定之一:变量、函数或数据成员之名,不论其类型,即使变量的类型是右值引用,由其名字构成的表达式仍是左值表达式。
因此尽管rr5的类型是右值引用,表达式rr5求值时,会转换成左值引用。