打赏

[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; }

 

posted @ 2020-08-23 19:24  listenviolet  阅读(198)  评论(0编辑  收藏  举报