c++ 右值引用移动构造函数
测试代码:
// 测试移动构造函数
class MyStr {
private:char* data;size_t size;
public:MyStr() : data(nullptr), size(0) {}MyStr(const char* str) :size(strlen(str)) {data = new char[size + 1];strcpy_s(data, size + 1, str);}// 移动构造函数(参数为右值引用) , 直接浅拷贝,等于将资源原封不动接管过来。MyStr(MyStr&& other) noexcept : data(other.data), size(other.size) {cout << "调用移动构造函数。 字符串:" << other.data << endl;other.data = nullptr; // 转移后置空原对象指针other.size = 0;}// 移动赋值运算符MyStr& operator=(MyStr&& other) noexcept {cout << "调用移动赋值。 字符串: " << other.c_str() << endl;if (this != &other) {delete[] data; // 释放当前资源data = other.data; // 接管资源size = other.size;other.data = nullptr;other.size = 0;}return *this;}// 析构函数~MyStr() {cout << "析构: " << (data ? c_str() : "null") << endl;delete[] data;}const char* c_str() const { return data; }
};MyStr createString() {MyStr tmp("空洞派, 峨嵋派, 华山派, 武当派, 恒山派, 泰山派, 嵩山派"); // 构造了临时对象,属于右值return tmp; // 可能触发移动语义。除非编译器优化(RVO, 返回值优化, 直接在函数调用处构造该对象)
}// 测试代码:
void testYouZhiRef() {int num = 1;//int&& a = num; // 编译报错: 无法将右值引用绑定到左值int&& a = 9527; // 右值引用a = 250;cout << a << endl << endl;MyStr s1("我的战斗力有6000,他的起码有1万");std::cout << "s1: " << (s1.c_str() ? s1.c_str() : "null") << "\n\n";// 显式调用移动构造函数. 会将左值强制转化为右值。当使用右值对象(临时对象)初始化同类对象时,编译器优先选择调用移动构造函数。// 移动构造优先于拷贝构造MyStr s2 = std::move(s1);// 编译器报警:使用已移动的from对象:s1std::cout << "s1: " << (s1.c_str() ? s1.c_str() : "null") << "\n";std::cout << "s2: " << s2.c_str() << "\n\n";MyStr s3;s3 = createString(); // 函数返回值触发移动赋值std::cout << "s3: " << s3.c_str() << "\n";
}
打印:
ok. 移动语义避免不必要的资源复制,提高性能。