[C++] 右值引用
#include <iostream> #include <cstring> using namespace std; class A { public: char *p; A() { p = new char[3]; }; A(const A& a) { p = new char[3]; for(int i = 0; i < 3; ++i) { p[i] = a.p[i]; } } // 移动构造 A(A&& a) { cout << "in move constructor" << endl; p = a.p; a.p = nullptr; } // 移动赋值 A& operator=(A&& a) { cout << "in move = operator" << endl; p = a.p; a.p = nullptr; return *this; } ~A() {}; }; int main() { /** 1. 对基础类型变量(如int)进行move操作, move前后的变量(i, rr)指向了同一块内存空间; 如下例 (1) int &&rr = move(i); 之后i, rr对应同一块内存,值均为22; (2) i = 44; 之后,i,rr的值均为44 */ int i = 22; int &&rr = move(i); cout << "ori i = 22, move to rr" << endl; cout << "i = " << i << endl; // 22 cout << "rr = " << rr << endl; // 22 cout << endl; cout << "after i = 44" << endl; i = 44; cout << "i = " << i << endl; // 44 cout << "rr = " << rr << endl; // 44 cout << endl; /** 2. 对含有指针的类进行move操作 (1) 为什么需要move 类中如果含有指针,那么对类对象在进行拷贝时,要思考进行深拷贝还是浅拷贝; 如果进行浅拷贝,对于类中的指针类型,只能copy指针的地址,并不能复制指针指向的内容; 如果进行深拷贝,对于类中的指针类型,则重新开辟了一块内存空间,copy指针指向的内容; 但是对于一些被copy之后不会再被用到的类对象,却还占据着空间, 于是希望引入"move",把原对象的内存"偷"过来,接管对原对象内存空间的管理权, 以达到节约开销,提高性能的目的; (2) 如何move 对于类中的指针,在调用时一般是不可见的(如private类型的), 所以需要类的构造者在设计构造函数时,考虑如果将其进行拷贝or赋值操作时应如何处理指针。 对于move操作,有移动构造和移动赋值2种; 移动构造:在声明定义时进行初始化;见class A中的 A(A&& a) 移动赋值:用=赋值;见class A 中的 A& operator=(A&& a) 如果使用move,开发者要设计好类中的以上2中操作,一般是: 再创建一个新的指针, 用新指针地址 = 被复制对象的对应指针地址, 将被复制对象的对应指针 指向 设置为空。 */
A a; char *s = "ab"; a.p = s; cout << "a.p = " << endl; for(int i = 0; i < 3; ++i) { // 这里转int可以看到字符串是否以\0结束 cout << int(a.p[i]) << " "; // 97 98 0 } cout << endl; /////// 1. 普通的拷贝构造 ////////// A b(a); cout << "b.p = " << endl; for(int i = 0; i < 3; ++i) { cout << b.p[i] << " "; // a b } cout << endl; cout << endl; /////// 2. 移动赋值 c = move(a); ////////// // 这里将 char* 强转 int* 为了获取指针p的地址 // 如果不强转, C++在对char*输出时,会默认输出指针所指向地址的值(ex."ab") // 下例输出: // in move = operator // after A c = move(a) // a.p = 0x0 // c.p = 0x10e3d0edb A c; c = move(a); cout << "after A c = move(a)" << endl; cout << "a.p = " << (int*)a.p << endl; cout << "c.p = " << (int*)c.p << endl; /////// 3. 移动构造 A e(move(d)); ////////// // in move constructor // after e(move(d)) // d.p = 0x0 // e.p = 0x10e3d0f09 A d; char *s2 = "cd"; d.p = s2; A e(move(d)); cout << "after e(move(d))" << endl; cout << "d.p = " << (int*)d.p << endl; cout << "e.p = " << (int*)e.p << endl; return 0; }