关于std::move的疑惑:为何str3未触发移动语义而str4触发?
为什么右值引用变量构造不触发移动,直接传std::move却可以?
先把你两段代码的典型写法贴出来,方便对照:
第一段代码:
std::string str1 = "test content"; std::string&& str2 = std::move(str1); std::string str3(str2); // str1内容保留,未被移动
第二段代码:
std::string str1 = "test content"; std::string str4(std::move(str1)); // str1内容被移动,变为空
核心原因只有一个:具名的右值引用本身是左值。
拆解第一段代码的逻辑
std::move(str1)的作用是把str1这个左值强制转换成std::string&&类型的右值引用,但当你把这个引用赋值给具名变量str2后,str2就成了有名字的左值——编译器只会把无名的临时对象/亡值当作右值处理,只要是有名字的变量,不管它的类型是不是右值引用,都会被视为左值。- 所以用
str2构造str3时,编译器匹配的是std::string的拷贝构造函数(参数是const std::string&),做的是深拷贝,完全不会动str1的资源,自然str1的内容还在。
拆解第二段代码的逻辑
std::move(str1)直接作为构造函数的参数时,它返回的是一个无名的右值引用(属于亡值范畴),这时候编译器会优先匹配std::string的移动构造函数(参数是std::string&&)。- 移动构造函数会直接接管str1内部的内存资源(比如把str1的指针置空),所以构造完str4后,str1的内容就被转移走了。
额外验证:如果想让str2触发移动怎么办?
只要再用std::move把str2这个左值转换成右值就行:
std::string str3(std::move(str2)); // 此时str1的内容会被移动到str3,str1变为空
内容的提问来源于stack exchange,提问作者chaowen
相关产品推荐
相关产品推荐

