【现代C++】移动语义和右值引用
现代C++中的移动语义和右值引用是C++11引入的重要特性,旨在优化资源管理和提升性能。这些特性允许资源的转移而非复制,特别是对于临时对象和大型对象。
1. 右值引用
右值引用是对临时对象的引用,它允许你修改临时对象。使用&&
来声明右值引用。
#include <iostream>
void rightValueReference() {
int&& rvalueRef = 10; // 右值引用
rvalueRef = 20; // 修改临时对象
std::cout << rvalueRef << std::endl; // 输出20
}
2. 移动构造函数
移动构造函数允许资源在对象之间转移。当源对象是一个右值时,移动构造函数会被调用。
#include <iostream>
#include <vector>
class MoveableClass {
public:
std::vector<int> data;
// 移动构造函数
MoveableClass(MoveableClass&& other) noexcept : data(std::move(other.data)) {
std::cout << "Move constructor called" << std::endl;
}
};
void moveConstructor() {
MoveableClass a;
a.data = {1, 2, 3, 4, 5};
MoveableClass b = std::move(a); // 调用移动构造函数
}
3. 移动赋值运算符
移动赋值运算符允许将一个对象的资源转移到另一个对象。
#include <iostream>
#include <vector>
class MoveableClass {
public:
std::vector<int> data;
// 移动赋值运算符
MoveableClass& operator=(MoveableClass&& other) noexcept {
if (this != &other) {
data = std::move(other.data);
std::cout << "Move assignment called" << std::endl;
}
return *this;
}
};
void moveAssignment() {
MoveableClass a;
a.data = {1, 2, 3, 4, 5};
MoveableClass b;
b = std::move(a); // 调用移动赋值运算符
}
4. std::move
函数
std::move
将其参数转换为右值引用,允许发生移动语义。实际上,std::move
不移动任何东西,它只转换为右值引用。
#include <iostream>
#include <utility>
#include <vector>
void stdMoveFunction() {
std::vector<int> vec1 = {1, 2, 3, 4, 5};
std::vector<int> vec2 = std::move(vec1); // vec1的资源被转移到vec2
std::cout << "vec1 size: " << vec1.size() << std::endl; // 输出0
std::cout << "vec2 size: " << vec2.size() << std::endl; // 输出5
}
5. 移动语义和自定义类型
自定义类型可以通过实现移动构造函数和移动赋值运算符来利用移动语义。
#include <iostream>
#include <algorithm>
class MoveableClass {
private:
int* data;
public:
explicit MoveableClass(int size) {
data = new int[size];
std::fill_n(data, size, 42);
}
// 移动构造函数
MoveableClass(MoveableClass&& other) noexcept : data(other.data) {
other.data = nullptr;
}
// 移动赋值运算符
MoveableClass& operator=(MoveableClass&& other) noexcept {
if (this != &other) {
delete[] data;
data = other.data;
other.data = nullptr;
}
return *this;
}
~MoveableClass() {
delete[] data;
}
};
void moveSemanticsCustomType() {
MoveableClass obj1(10); // 普通构造函数
MoveableClass obj2(std::move(obj1)); // 移动构造函数
}