C++11:调用移动 ctor/operator= 时
C++11: when move ctor/operator= is called?
#include <iostream>
class Class
{
public:
Class() { std::cerr << "ctor" << std::endl; }
~Class() { std::cerr <<"dtor" << std::endl; }
Class(Class&) { std::cerr << "copy ctor" << std::endl; }
Class & operator=(const Class &)
{
std::cerr << "copy operator=" << std::endl;
return *this;
}
Class(Class&&) { std::cerr << "move ctor" << std::endl;}
Class & operator=(Class &&)
{
std::cerr << "move operator="<< std::endl;
return *this;
}
};
int main(int, char**)
{
Class object;
Class && rvr = Class();
object = rvr; // (*)
}
输出为
ctor
ctor
copy operator=
dtor
dtor
1) 为什么在第 (*) 行调用"复制 ctor"?
2)如果我每次都必须使用std::move(),那么"移动语义"和任何移动数据的方法(如object.destructive_move();
)有什么区别?
3) 何时调用移动 CTOR/操作员?
谢谢!
复制 ctor 不是在第 (*) 行调用的,而是调用复制赋值运算符。我想这就是你的意思。
调用的是复制赋值运算符,而不是移动赋值运算符,因为rvr
是左值。请注意,表达式的类型与它是否为左值正交。
如果将赋值语句修改为 object = Class();
甚至 object = static_cast<Class&&>(rvr)
,您会发现正在调用移动赋值运算符,因为在这两种情况下 RHS 都是右值。
这种行为是明智的:例如,考虑移动分配运算符的实现。它的参数具有右值引用类型,但它仍然是左值。如果它是右值,那么第一次使用该参数可能会修改其状态以成为"空"对象(移动语义),然后第二次使用该参数可能无法按预期工作。
它的实际工作方式是,当您想要以使其处于"空"状态的方式使用该参数时,您将显式使用 std::move
。
Class && rvr = Class();
我要说的是没有意义,但这是C++11规则。
rvr
是一个变量,它是对Class
的右值引用。这很容易理解。但重要的是要理解这一点:命名变量从来都不是右值表达式。即使它是右值引用!
同样,我知道这没有意义,但这是规则。右值引用变量不是右值表达式。
临时是一个右值表达式,因此Class()
为您提供右值。从函数返回的临时函数也是一个右值表达式,因此,如果您有一些按值返回Class
函数,您将获得一个右值。
这很重要,因为如果您有两个基于左值和右值引用的函数重载(如复制/移动构造函数/赋值),则仅当表达式类型为右值时,C++11 才会选择右值引用版本。
这就是std::move
存在的原因。它的存在是为了明确说明何时要移动某些内容。它通过将您赋予它的值转换为右值表达式来实现此目的。也就是说,它返回Class&&
.
这是真正令人困惑的部分。如果您有命名的右值引用变量,则不是右值表达式。但是,如果您有未命名的右值引用,例如从函数返回Class&&
,那就是右值表达式。
std::move
返回Class&&
.因此,如果要从命名变量移动,则必须始终对其调用std::move
。因此,如果要从 rvr
,则必须执行以下操作:
object = std::move(rvr); // (*)
这将返回Class&&
给rvr
。将发生C++11过载解决方案。由于要operator=
的参数是右值表达式,因此它将选择operator=
的右值引用版本。从而调用一个动作。
请注意,std::move
实际上只是对半复杂演员表的包装。它不做移动;是operator=
在做移动。
- std::is_base_of表示ctor编译错误
- 为什么 std::optional::operator=(U&&) 要求你是非标量类型?
- 'operator='已弃用:改用 QDir::setPath()
- 过载'operator new'如何导致无限循环?
- 对复制 CTOR 和 CTOR 的未定义引用
- 与'operator='不匹配(操作数类型'String'且"void")
- SegFault 同时使用 std::string::operator+= 和函数作为参数
- 处理"no operator found"
- C++ 基本 CTOR 说明 - 为什么不调用赋值/复制构造函数
- 如何编写 operator= 用于使用虚拟方法与非平凡成员的匿名联合
- 运算符重载:"operator+"必须采用零个或一个参数
- 使用 operator() 扩展 Eigen::EigenBase
- 错误消息:使用"string* +="后"no match for 'operator+='"
- 有没有办法修改'operator->',以便'z->im'返回复数的虚部
- "operator +="行为异常的定义
- C++ "error: use of overloaded operator '*' is ambiguous"似乎只有一场比赛
- 错误:二进制'operator*' 'float'和'float[0]'类型的操作数无效
- 在 Eclipse: "error: no match for 'operator='" 中获取错误消息
- 为什么 operator() 处的指针成员不起作用?
- C++11:调用移动 ctor/operator= 时