• [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.
    
    **/

  • 相关阅读:
    Linux下几种文件传输命令 sz rz sftp scp
    jqGrid subGrid配置 如何首次加载动态展开所有的子表格
    MySQL使用规范
    Navicat连接MySQL报错2059
    微信小程序
    完美解决 ios10 及以上 Safari 无法禁止缩放的问题
    html5利用getObjectURL获取图片路径上传图片
    Vue的单页应用中如何引用单独的样式文件
    用JS添加和删除class类名
    APP中的 H5和原生页面如何分辨、何时使用
  • 原文地址:https://www.cnblogs.com/shiyublog/p/13514963.html
Copyright © 2020-2023  润新知