一、移动构造函数在以下几种情况下会被调用:
-
返回值优化:当一个对象作为函数的返回值时,移动构造函数可以将临时对象的资源转移到接收对象,而不是复制资源。
MyClass createObject() { MyClass obj; return obj; // 调用移动构造函数 }
-
容器操作:当将对象插入到 STL 容器(如
std::vector
、std::map
等)中时,如果容器需要扩展或重分配内存,可能会调用移动构造函数来转移现有对象的资源。std::vector<MyClass> vec; MyClass obj; vec.push_back(std::move(obj)); // 调用移动构造函数
-
使用
std::move
:当你显式地使用std::move
来转换一个对象为右值时,会调用移动构造函数。MyClass obj; MyClass newObj = std::move(obj); // 调用移动构造函数
-
初始化列表:在构造函数的初始化列表中,如果使用了右值,会调用移动构造函数。
class MyClass { public: MyClass(MyClass&& other) { /* 移动构造 */ } }; MyClass obj1; MyClass obj2(std::move(obj1)); // 调用移动构造函数
总之,任何时候当一个对象被视为右值(即可以“移动”的对象)时,都会调用移动构造函数。
二、移动赋值运算符在以下几种情况下会被调用:
-
赋值操作:当一个已存在的对象被赋值一个右值(例如临时对象或使用
std::move
的对象)时,会调用移动赋值运算符。MyClass obj1; MyClass obj2; obj1 = std::move(obj2); // 调用移动赋值运算符
-
容器操作:在 STL 容器中,如果需要对已存在的元素进行赋值操作,并且新赋值的元素是一个右值,移动赋值运算符将被调用。
std::vector<MyClass> vec(2); MyClass obj; vec[0] = std::move(obj); // 调用移动赋值运算符
-
初始化列表:如果在类的构造函数中使用初始化列表来赋值现有对象,并且使用了右值,也会调用移动赋值运算符。
class MyClass { public: MyClass& operator=(MyClass&& other) { /* 移动赋值 */ return *this; } }; MyClass obj1; MyClass obj2; obj1 = std::move(obj2); // 调用移动赋值运算符
-
函数参数:在函数参数中,如果参数是以值传递的,并且是右值,可能会调用移动赋值运算符。
void func(MyClass obj) { MyClass anotherObj; anotherObj = std::move(obj); // 调用移动赋值运算符 }
总结来说,任何时候当一个对象被赋值为右值时,移动赋值运算符就会被调用。这使得资源可以高效地转移而不是复制。