-
移动语义的的本质其实也是复制,但是和普通的拷贝复制不同。对于 动态分配的内存 和其他大型的资源,拷贝的话 开销会很大 。而移动语义就是 让对象的资源被移动 到新对象,而不是去拷贝,从而节省资源和时间。
-
移动语义 通过 移动构造函数 和 移动赋值运算符 实现。源对象的资源 被转移到目标对象,源对象变为无效状态。
cpp
#include <iostream>
#include <vector>
class MyVector {
public:
MyVector(size_t size) : data(new int[size]), size(size) {
std::cout << "Constructing MyVector of size " << size << std::endl;
}
// 移动构造函数
MyVector(MyVector&& other) noexcept : data(other.data), size(other.size) {
other.data = nullptr; // 将原对象的指针设为空
other.size = 0;
std::cout << "Moving MyVector of size " << size << std::endl;
}
// 移动赋值运算符
MyVector& operator=(MyVector&& other) noexcept {
if (this != &other) {
delete[] data; // 释放当前对象的内存
data = other.data; // 移动资源
size = other.size;
other.data = nullptr; // 将原对象的指针设为空
other.size = 0;
std::cout << "Moving assignment of MyVector of size " << size << std::endl;
}
return *this;
}
~MyVector() {
delete[] data; // 释放资源
std::cout << "Destroying MyVector" << std::endl;
}
private:
int* data;
size_t size;
};
int main() {
MyVector vec1(10); // 构造一个对象
MyVector vec2 = std::move(vec1); // 移动构造
MyVector vec3(5);
vec3 = std::move(vec2); // 移动赋值
return 0;
}
- 移动语义:通过移动构造函数来实现。
cpp
class A {
public:
A(int size) : size_(size) {
data_ = new int[size];
}
A(){}
A(const A& a) {
size_ = a.size_;
data_ = new int[size_];
cout << "copy " << endl;
}
A(A&& a) { //移动资源不是自动实现的,而是我们程序员自己在移动构造函数里写出来的逻辑
this->data_ = a.data_;
a.data_ = nullptr;
cout << "move " << endl;
}
~A() {
if (data_ != nullptr) {
delete[] data_;
}azs
}
int *data_;
int size_;
};
int main() {
A a(10);
A b = a;
A c = std::move(a); // 调用移动构造函数(把对象改为右值后,就会调用移动构造函数了)
return 0;
}
- 使用移动语义可以避免很多无用的拷贝,提供程序性能,C++所有的STL都实现了移动语义,方便我们使用:
cpp
std::vector<string> vecs;
...
std::vector<string> vecm = std::move(vecs); // 免去很多拷贝
(注意:移动语义仅针对于那些实现了移动构造函数的类的对象,对于那种基本类型int、float等没有任何优化作用,还是会拷贝,因为它们实现没有对应的移动构造函数)