对象移动的概念
对象移动是将资源的所有权从一个对象转移到另外的一个对象, 而不是进行深拷贝, 来避免不必要的数据复制和内存分配.
移动构造函数和移动赋值运算符
移动构造函数
移动构造函数概念
移动构造函数用于将一个对象资源所有权转移到另外的一个对象上,她接受一个右值引用作为参数, 并且通常会将源对象的资源指针设置为nullptr, 以避免资源的重复释放.
移动构造函数的语法
ClassName(ClassName && obj) noexcept
{
// 将资源所有权转移从obj转移到当前对象
// 将obj的资源指针设置为nullptr
}
noexcept: 告诉标准库移动构造函数不生成任何异常
移动构造函数常用于情况:
1, 在函数返回时, 将局部对象的资源移动到返回值对象中
2, 在函数传递参数时, 将一个对象的资源移动到另外一个对象中
3, 在对象初始化列表中, 通过std::move()将一个对象的资源移动到另外的一个对象中.
移动赋值运算符
移动赋值运算符概念
移动赋值运算符用于将一个对象的资源所有权转移到一个已经存在的对象.他接受一个右值引用为参数, 并且通常会将源对象的资源指针设置为nullptr, 以避免资源的重复释放
移动赋值运算符语法
ClassName & operator=(ClassName && obj) noexcept
{
if(this != & obj)
{
// 释放当前对象的资源
// 将资源所有权转移从obj转移到当前对象
// 将obj的资源指针设置为nullptr
}
return *this;
}
移动赋值运算符常用情况
1, 在赋值语句中, 将一个对象的资源移动到另外一个已经存在的对象中.
2, 在对象初始化列表中, 通过std::move()将一个对象的资源移动到另外一个已经存在的对象中
案例演示
#include<iostream>
using std::cout;
using std::endl;
class A
{
public:
int x;
A() : x(100) { cout << "执行类A的默认构造函数" << endl; }
A(const A& a) : x(a.x) { cout << "执行类A的复制构造函数" << endl; }
~A() { cout << "执行类A的析构函数" << endl; }
};
class B
{
public:
A* pa;
B() : pa(new A()) { cout << "执行类B的默认构造函数" << endl; }
B(const B& b) : pa(new A(*(b.pa))) { cout << "执行类B的复制构造函数" << endl; }
B(B&& obj) noexcept: pa(obj.pa) { obj.pa = nullptr; cout << "类B的移动构造函数执行" << endl; }
~B() { delete pa; cout << "执行类B的析构函数" << endl; }
B& operator=(B&& b)
{
if (this != &b)
{
delete pa;
pa = new A(*(b.pa));
b.pa = nullptr;
return *this;
}
return *this;
}
};
static B getB()
{
B temp;
return temp; // 临时对象, 调用构造函数
// 如果B有移动构造函数就会调用移动构造函数, 将a的值移动到临时对象,返回临时对象
}
移动构造函数的生成时机:
1, 类中如果显示的定义, 复制构造函数, 赋值运算符重载, 析构函数,编译器不会生产移动函数
2, 若存在显示的复制构造函数, 赋值运算符重载, 系统会调用这个两个函数来代替移动函数的功能
3, 类没有显示定义任何拷贝函数, 且非静态成员是可以移动的,
可以移动: 基本类型可以移动, 类类型成员,且这个成员有自己定义的移动函数.