zoukankan      html  css  js  c++  java
  • [C++] 深拷贝和浅拷贝

    c++的类中含有指针类型时,在进行拷贝时要注意深拷贝和浅拷贝的问题。

    (1) 浅拷贝采用"位拷贝"的方式。对于基础类型,如int, float等,可以直接copy过来;

    但是对于指针类型,在copy时要格外注意,浅拷贝只copy了指针指向的地址,并未复制创建该地址上的对象内容,容易引发内存泄露、多次析构等问题。

    (2) 深拷贝则为新对象的成员重新开辟内存空间,每个对象共同拥有自己的资源,必须显式提供拷贝构造函数和赋值运算符。

    1. 浅拷贝的问题

    以类File为例,首先创建了File类型的一个对象a, File类型的对象b是由a 浅拷贝得到。

    在浅拷贝时,对于a中的指针类型对象_fp,b只copy了a中_fp指针指向的对象的地址

    那么浅拷贝后,a, b对象的_fp指针都指向了同一块内存

    这在类进行析构时很容易出现被多次析构的问题。 

    #include <iostream>
    using namespace std;
    
    class File
    {
    public:
        explicit File(const char *file_name) {};
        ~File() {};
    
        void addr_fp() {
            cout << _fp << endl;
        }
    
    private:
        FILE *_fp; 
    };
    
    int main()
    {
        File a("./a.txt");
        cout << "a._fp addr" << endl;
        a.addr_fp();
    
        File b = a;
        cout << "b._fp addr" << endl;
        b.addr_fp();
    
        return 0;
    }
    
    /** output
    
    a._fp addr
    0x7ffee45649d8
    b._fp addr
    0x7ffee45649d8
    
    **/

    2. 解决方法

    对于含有指针类型的类,可以采用进制拷贝构造、赋值构造等方式来避免(1)中的问题。(RAII没有复制行为)

    下例中通过定义一个拷贝和赋值构造的宏,并在private中进行声明,

    那么如果有企图对该类对象进行拷贝或赋值构造,会触发private 的constructor引发报错。

    #include <iostream>
    using namespace std;
    
    #define DISALLOW_COPY_AND_ASSIGN(TypeName) 
            TypeName(const TypeName&);
            TypeName& operator=(const TypeName&) 
    
    
    class File
    {
    public:
        explicit File(const char *file_name) {};
        ~File() {};
    
        void addr_fp() {
            cout << _fp << endl;
        }
    
    private:
        FILE *_fp; 
        DISALLOW_COPY_AND_ASSIGN(File);
    };
    
    int main()
    {
        File a("./a.txt");
        cout << "a._fp addr" << endl;
        a.addr_fp();
    
        File b = a;
        cout << "b._fp addr" << endl;
        b.addr_fp();
    
        return 0;
    }
    
    
    /** output
    
    deep_shallow_copy.cpp:30:11: error: calling a private constructor of class 'File'
            File b = a;
                     ^
    deep_shallow_copy.cpp:21:27: note: declared private here
            DISALLOW_COPY_AND_ASSIGN(File);
                                     ^
    1 error generated.
    
    **/

  • 相关阅读:
    【题解】B进制星球
    高斯消元
    7.16
    题解 P1572 【计算分数】
    7.30
    7.31
    项目中使用 MyBatis(一)
    从整体上了解Spring MVC
    Spring注解
    Spring IOC 和 DI
  • 原文地址:https://www.cnblogs.com/shiyublog/p/13514963.html
Copyright © 2011-2022 走看看