拷贝构造函数

拷贝构造函数

拷贝构造函数一般为:

类名(const 类名& C);它必须的一个参数是本类型的一个引用变量

默认的拷贝构造函数是浅拷贝。

拷贝构造函数常出现的地方:

a对象以值传递的方式传入函数参数

//全局函数,传入的是对象

void g_Fun(CExample C)

{

 cout<<"test"<<endl;

}

 

int main()

{

 CExample test(1);

 g_Fun(test);

//当调用g_Fun()时,会产生以下几个重要步骤:创建一个临时的对象,调用拷贝构造函数将test的值拷贝到这个临时对象中,等g_Fun()执行完后, 析构掉这个临时对象,这也是为什么我们传对象的时候传数值比传指针(或者是引用对象)慢的原因。

 return 0;

}

测试:

         class CExample

         {

         private:

                   int a;

 

         public:

                   //构造函数

                   CExample(int b)

                   {

                            a = b;

                            cout << "creat: " << a << endl;

                   }

 

                   //拷贝构造

                   CExample(const CExample& C)

                   {

                            a = C.a;

                            cout << "copy" << endl;

                   }

 

                   //析构函数

                   ~CExample()

                   {

                            cout << "delete: " << a << endl;

                   }

 

                   void Show()

                   {

                            cout << a << endl;

                   }

         };

 

         //全局函数,传入的是对象

         void g_Fun(CExample C)

         {

                   cout << "test" << endl;

         }

 

         void fun1()

         {

                   CExample test(1);

                   //传入对象,也就是传数值

                   g_Fun(test);

                   ///当调用g_Fun()时,会产生以下几个重要步骤:创建一个临时的对象,调用拷贝构造函数将test的值拷贝到这个临时对象中,等g_Fun()执行完后, 析构掉这个临时对象,这也是为什么我们传对象的时候传数值比传指针(或者是引用对象)慢的原因。

         }

运行结果:

B、对象以值传递的方式从函数返回

CExample1 g_Fun2()

    {

        cout << "g_Fun2函数:" << endl;

        CExample1 temp(111);

        return temp;

        //当这个函数执行到return时,先会创建一个临时变量,再调用拷贝构造函数把temp的值拷贝到这个临时变量中,等这个函数执行到最后,析构temp局部变量,再将这个临时变量作为返回对象返回

    }

 

    void text2()

    {

        CExample1 pC = g_Fun2();

        cout << "主函数:" << endl;

        pC.Show();

    }

结果:

 

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

//(3)对象需要通过另外一个对象进行初始化

    void text3()

    {

        CExample1 A(100);

        CExample1 B = A;//在这里相当于CExample B(A);是调用了拷贝构造函数,如果类中没有定义自己的拷贝构造函数,系统会调用系统自带的,但是自带的拷贝构造函数只是将对象的数值拷贝过去,如果是类中有指针对象时,此时容易出现错误,即A,B两个类对象,对应的指针变量,由于拷贝构造函数只将A的指针只拷贝数值给B对应的指针,这样两个指针指向同一块内存上,释放的时候同一块内存释放2次出现错误,要解决这个问题就要用到 浅拷贝(只拷贝数值)和深拷贝(即拷贝数值,也同时针对指针创建内存),主要区别:针对有指针的类,指针指向的内存,他是否会为其再申请空间,回再申请空间的就是深拷贝,否则就是浅

 

    }

 

浅拷贝

所谓浅拷贝,指的是在对象复制时,只对对象中的数据成员进行简单的赋值,默认拷贝构造函数执行的也是浅拷贝。针对有指针的类,指针指向的内存,他不会为其再申请空间,只是简单的把两个指针的值拷贝下,即两个指针指向同一块内存,易出现同一块内存上,释放的时候同一块内存释放2次出现错误。

深拷贝主要是针对有指针的类,指针指向的内存,他会为其再申请空间,再把数值拷贝进去,为新对象重新动态分配空间

//深拷贝

    class Rect

    {

    public:

        Rect()      // 构造函数,p指向堆中分配的一空间

        {

            p = new int(100);

        }

        Rect(const Rect& r)

        {

            width = r.width;

            height = r.height;

            p = new int;    //区别深拷贝与浅拷贝关键: 深拷贝主要是针对有指针的类,指针指向的内存,他会为其再申请空间,再把数值拷贝进去,为新对象重新动态分配空间

            *p = *(r.p);

        }

        ~Rect()     // 析构函数,释放动态分配的空间

        {

            if (p != NULL)

            {

                delete p;

            }

        }

    private:

        int width;

        int height;

        int *p;     // 一指针成员

    };

 

    void test4()

    {

        Rect p1;

        Rect p2 = p1;

    }

防止默认拷贝发生

将拷贝构造函数设置为私有的

// 防止按值传递

    class CExample

    {

    private:

        int a;

 

    public:

        //构造函数

        CExample(int b)

        {

            a = b;

            cout << "creat: " << a << endl;

        }

 

    private:

        //拷贝构造,只是声明

        CExample(const CExample& C);

 

    public:

        ~CExample()

        {

            cout << "delete: " << a << endl;

        }

 

        void Show()

        {

            cout << a << endl;

        }

    };

 

    //全局函数

    void g_Fun(CExample C)

    {

        cout << "test" << endl;

    }

 

    int main()

    {

        CExample test(1);

        //g_Fun(test); 按值传递将出错

 

        return 0;

    }

 

拷贝构造函数和赋值符的区别

CTest a;

 CTest b(a);

 CTest c = a; //注意,这里仍然是使用复制构造函数

 a = c;       //使用赋值符

1从概念上区分:
复制构造函数是构造函数,而赋值操作符属于操作符重载范畴,它通常是类的成员函数
复制构造函数原型ClassType(const ClassType &);无返回值
赋值操作符原型ClassType& operator=(const ClassType &);返回值为ClassType的引用,便于连续赋值操作
3.从使用的场合来区分:
复制构造函数用于产生对象,它用于以下几个地方:函数参数为类的值类型时、函数返回值为类类型时以及初始化语句,而赋值操作符要求‘=’的左右对象均已存在,它的作用就是把‘=’右边的对象的值赋给左边的对象
4.当类中含有指针成员时,两者的意义有很大区别
复制构造函数需为指针变量分配内存空间,并将实参的值拷贝到其中;而赋值操作符它实现的功能仅仅是将‘=’号右边的值拷贝至左值,在左边对象内存不足时,先释放然后再申请。当然赋值操作符必须检测是否是自身赋值,若是则直接返回当前对象的引用而不进行赋值操作

posted on 2015-09-25 16:35  淡如清风  阅读(218)  评论(0编辑  收藏  举报

导航