C++11:何时调用move ctor/operator=?

C++11:何时调用move ctor/operator=?,c++,c++11,C++,C++11,1为什么在第*行调用复制ctor 2如果我每次都必须使用std::move,那么move语义和任何移动数据的方法(如object.destructive_move;)之间有什么区别 3何时调用移动选择器/运算符 谢谢 第*行不调用复制ctor,调用复制赋值运算符。我想这就是你的意思 由于rvr是左值,因此调用的是复制赋值运算符,而不是移动赋值运算符。请注意,表达式的类型与是否为左值正交 如果将赋值语句修改为object=Class;或者甚至object=static,您会发现调用了move赋值操

1为什么在第*行调用复制ctor

2如果我每次都必须使用std::move,那么move语义和任何移动数据的方法(如object.destructive_move;)之间有什么区别

3何时调用移动选择器/运算符


谢谢

第*行不调用复制ctor,调用复制赋值运算符。我想这就是你的意思

由于rvr是左值,因此调用的是复制赋值运算符,而不是移动赋值运算符。请注意,表达式的类型与是否为左值正交

如果将赋值语句修改为object=Class;或者甚至object=static,您会发现调用了move赋值操作符,因为在这两种情况下,RHS是一个右值

这种行为是合理的:考虑移动分配操作符的实现,比如说。其参数的类型为右值引用,但它仍然是左值。如果它是一个右值,那么第一次使用参数可能会将其状态修改为“空”对象移动语义,然后第二次使用参数可能无法按预期工作

按照它的实际工作方式,当您希望以使参数保持“空”状态的方式使用参数时,可以显式地使用std::move

ctor
ctor
copy operator=
dtor
dtor
我要说的没有意义,但这是C++11规则

rvr是一个变量,是对类的右值引用。这很容易理解。但理解这一点很重要:命名变量永远不是右值表达式。即使它是右值引用

再说一次,我知道这没有道理,但这是规则。右值引用变量不是右值表达式

临时值是一个右值表达式,所以类为您提供一个右值。从函数返回的临时值也是一个右值表达式,因此,如果有某个函数按值返回类,则会返回右值

这很重要,因为如果有两个基于左值和右值引用(如复制/移动构造函数/赋值)重载的函数,C++11将仅在表达式类型为右值时选择右值引用版本

这就是std::move存在的原因。它的存在是为了明确说明何时要移动某个对象。它通过将给定的值转换为右值表达式来实现。也就是说,它返回类&&

这是一个令人困惑的部分。如果有命名的右值引用变量,则该变量不是右值表达式。但是,如果您有一个未命名的右值引用,例如从函数返回类&&则这是一个右值表达式

std::move返回类&&。因此,如果要从命名变量移动,必须始终对其调用std::move。因此,如果要从rvr移动,必须执行以下操作:

Class && rvr = Class(); 
这将向rvr返回一个类&&。将发生C++11重载解析。由于operator=的参数是一个右值表达式,因此它将选择operator=的右值引用版本。从而引发了一场运动


请注意,std::move实际上只是半复杂类型转换的包装器。它不会移动;是操作员=进行移动。

静态\u-vr-这对我来说很有趣。。。RVR已经是类& & @ USE1494506:是的,演员没有改变它的类型,我只是利用了一个副作用,即它的结果是一个特定的值,一个xValue.USS1494506:引入R值引用需要C++委员会对“LValueVS”的旧分类进行细化。现在有三个基本类别:“左值”、“xvalue”和“prvalue”纯右值。前两个统称为“glvalue”广义左值,后两个统称为“rvalue”。@user1494506:prvalue的典型示例为“true”、“5”,是函数的非引用返回值,它们的共同特性是没有“标识”-没有内存位置。相比之下,glvalue具有“标识”。大多数GLV值只是普通的左值,例如局部变量。有趣的例子是一个返回右值引用的函数,比如static_cast和std::move。由于它是一个引用,所以它有一个“标识”内存位置,但它仍然被视为即将过期-其内容可以重用-因此它被归类为“xvalue”。谢谢!!我快速看了一下std::move实现,事实上它是静态的\u cast;它是否只可能是xvalue?那么为什么object=*&rvr;还调用复制运算符=?*&rvr不应该像std::movervr那样创建右值表达式吗?@user1494506:No。获取一个指针,即&rvr是什么:类*并用*引用它,总是返回一个左值引用。没有类&&*或类&*。
Class && rvr = Class(); 
object = std::move(rvr); // (*)