zoukankan      html  css  js  c++  java
  • [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可以看到字符串是否以结束 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; }

  • 相关阅读:
    Kafka 生产者 自定义分区策略
    同步互斥
    poj 1562 Oil Deposits(dfs)
    poj 2386 Lake Counting(dfs)
    poj 1915 KnightMoves(bfs)
    poj 1664 放苹果(dfs)
    poj 1543 Perfect Cubes (暴搜)
    poj 1166 The Clocks (暴搜)
    poj 3126 Prime Path(bfs)
    处理机调度
  • 原文地址:https://www.cnblogs.com/shiyublog/p/13550257.html
Copyright © 2011-2022 走看看