zoukankan      html  css  js  c++  java
  • c++拷贝构造函数(深拷贝、浅拷贝)——转

    拷贝构造函数:

    拷贝构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它的唯一的一个参数是本类的一个引用变量,该参数是const类型,不可变的。例如:类A的拷贝构造函数的形式为A(A& x)。当用一个已经初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝函数就会被自动调用。也就是说,当类的对象需要拷贝时,拷贝构造函数将会被调用。以下情况会自动调用拷贝构造函数:

      1、一个对象以值传递的方式传入函数体

      2、一个对象以值传递的方式从函数返回,如下:

    #include <iostream>
    using namespace std;
    class B
    {
    public:
        B(){cout<<"构造函数B"<<endl;}
        B(int i):data(i){cout<<"构造函数B"<<" "<<data<<endl;}
        B play(B b){return b;}
        ~B(){cout<<"析构函数B"<<endl;}
    private:
        int data;
    };
    int main()
    {
        B temp;
        temp.play(5);
        return 0;
    }
    View Code

      3、一个对象需要通过另一个对象进行初始化

    如果在类中没有显示地声明一个拷贝构造函数,那么编译器会自动生成一个默认的拷贝构造函数,该构造函数完成对象之间的拷贝。自定义拷贝构造函数是一种良好的编程风格,它可以阻止编译器形成默认的拷贝构造函数,提高源码效率。

    深拷贝和浅拷贝:

    在某些情况下,类内成员变量需要动态开辟堆内存,如果实行位拷贝(位拷贝又称浅拷贝),也就是把对象里面的值完全复制给另一个对象,如A=B。这时,如果B中有一个成员变量指针已经申请了内存,那A中的那个成员也指向同一块内存。这就出现了问题:把B内存释放了,这时A内的指针就是野指针了,出现运行错误。

    深拷贝和浅拷贝可以简单理解为:如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之没有重新分配资源就是浅拷贝。

    浅拷贝:如果复制的对象中引用了一个外部内容(例如分配在堆上的数据),那么在复制这个对象的时候,让新旧两个对象指向同一个外部内容,就是浅拷贝。(指针虽然复制了,但所指向的空间内容并没有复制,而是由两个对象共用,两个对象不独立,删除空间存在)

    #include <iostream>
    #include <string.h>
    using namespace std;
    class Example
    {
    private:
        int a;
        char *str;
    public:
        Example()
        {
            cout<<"调用构造函数"<<endl;
        }
        ~Example()
        {
            cout<<"调用析构函数"<<endl;
        }
    
        Example(int b)
        {
            a=b;
    cout<<"调用构造函数"<<endl;
        }
        Example(const Example& example)//自定义拷贝构造函数
        {
            a=example.a;
        }
        void show()
        {
            cout<<a<<endl;
        }
    };
    
    int main()
    {
        Example a1(10);
        Example a2=a1;
        a2.show();
        return 0;
    }

    输出:

      调用构造函数

      10

      调用析构函数

      调用析构函数 

    深拷贝:如果在复制这个对象的时候为新对象制作了外部对象的独立复制,就是深拷贝。

    #include <iostream>
    #include <string.h>
    using namespace std;
    class Example
    {
    private:
        int a;
        char *str;
    public:
        Example()
        {
            cout<<"调用构造函数"<<endl;
        }
        ~Example()
        {
            delete str;
            cout<<"调用析构函数"<<endl;
        }
    
        Example(int b,char* e_str)
        {
            a=b;
            str=new char[b];
            strcpy(str,e_str);
         cout<<"调用构造函数"<<endl;
        }
        Example(const Example& example)//自定义拷贝构造函数
        {
            a=example.a;
            str=new char[a];//深拷贝
            if(str!=0)
                strcpy(str,example.str);
        }
        void show()
        {
            cout<<str<<endl;
        }
    };
    
    int main()
    {
        Example a1(10,"Hello");
        Example a2=a1;
        a2.show();
        return 0;
    }

    输出:

      调用构造函数

      Hello

      调用析构函数

      调用析构函数

    参考地址:https://www.cnblogs.com/BlueTzar/articles/1223313.html

  • 相关阅读:
    解剖Nginx·自动脚本篇(7)类型相关脚本系列
    解剖Nginx·自动脚本篇(6)编译器名称变量脚本 auto/cc/name
    解剖Nginx·自动脚本篇(5)编译器相关主脚本
    解剖Nginx·自动脚本篇(4)工具型脚本系列
    解剖Nginx·自动脚本篇(3)源码相关变量脚本 auto/sources
    解剖Nginx·自动脚本篇(2)设置初始变量脚本 auto/init
    解剖Nginx·自动脚本篇(1)解析配置选项脚本 auto/options
    解剖Nginx·模块开发篇(5)解读内置非默认模块 ngx_http_stub_status_module
    jupyter nb + scite 混合搭建成我的最爱IDE
    md语法之行内代码和代码片续集
  • 原文地址:https://www.cnblogs.com/ybf-yyj/p/9319765.html
Copyright © 2011-2022 走看看