C++拷贝构造函数(深拷贝,浅拷贝)

对于普通类型的对象来说,它们之间的复制是很简单的,例如:   int a=88;   int b=a;   而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量。下面看一个类对象拷贝的简单例子。

   #include
   using namespace std;
   class CExample {
   private:
   int a;
   public:
   CExample(int b)
   {
   a=b;
   }
   void Show ()
   {
   cout<<a<<endl; </a<<endl;
   }
   };
   int main()
   {
   CExample A(100);
   CExample B=A;
   B.Show ();
   return 0;
   }

  运行程序,屏幕输出100。从以上代码的运行结果可以看出,系统为对象B分配了内存并完成了与对象A的复制过程。就类对象而言,相同类型的类对象是通过拷贝构造函数来完成整个复制过程的。下面举例说明拷贝构造函数的工作过程。

   #include
   using namespace std;
   class CExample {
   private:
   int a;
   public:
   CExample(int b)
   { a=b;}
   CExample(const CExample& C)
   {
   a=C.a;
   }
   void Show ()
   {
   cout<<a<<endl; </a<<endl;
   }
   };
   int main()
   {
   CExample A(100);
   CExample B=A;
   B.Show ();
   return 0;
   }

  CExample(const CExample& C)就是我们自定义的拷贝构造函数。可见,拷贝构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它的唯一的一个参数是本类型的一个引用变量,该参数是const类型,不可变的。例如:类X的拷贝构造函数的形式为X(X& x)。   当用一个已初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝构造函数就会被自动调用。也就是说,当类的对象需要拷贝时,拷贝构造函数将会被调用。以下情况都会调用拷贝构造函数:   一个对象以值传递的方式传入函数体   一个对象以值传递的方式从函数返回   一个对象需要通过另外一个对象进行初始化。   如果在类中没有显式地声明一个拷贝构造函数,那么,编译器将会自动生成一个默认的拷贝构造函数,该构造函数完成对象之间的位拷贝。位拷贝又称浅拷贝,后面将进行说明。   自定义拷贝构造函数是一种良好的编程风格,它可以阻止编译器形成默认的拷贝构造函数,提高源码效率。   浅拷贝和深拷   在某些状况下,类内成员变量需要动态开辟堆内存,如果实行位拷贝,也就是把对象里的值完全复制给另一个对象,如A=B。这时,如果B中有一个成员变量指针已经申请了内存,那A中的那个成员变量也指向同一块内存。这就出现了问题:当B把内存释放了(如:析构),这时A内的指针就是野指针了,出现运行错误。   深拷贝和浅拷贝可以简单理解为:如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝。下面举个深拷贝的例子。

   #include
   using namespace std;
   class CA
   {
   public:
   CA(int b,char* cstr)
   {
   a=b;
   str=new char;
   strcpy(str,cstr);
   }
   CA(const CA& C)
   {
   a=C.a;
   str=new char[a]; //深拷贝
   if(str!=0)
   strcpy(str,C.str);
   }
   void Show()
   {
   cout<<str<<endl; </str<<endl;
   }
   ~CA()
   {
   delete str;
   }
   private:
   int a;
   char *str;
   };
   int main()
   {
   CA A(10,"Hello!");
   CA B=A;
   B.Show();
   return 0;
   }

  深拷贝和浅拷贝的定义可以简单理解成:如果一个类拥有资源(堆,或者是其它系统资源),当这个类的对象发生复制过程的时候,这个过程就可以叫做深拷贝,反之对象存在资源,但复制过程并未复制资源的情况视为浅拷贝。   浅拷贝资源后在释放资源的时候会产生资源归属不清的情况导致程序运行出错。   Test(Test &c_t)是自定义的拷贝构造函数,拷贝构造函数的名称必须与类名称一致,函数的形式参数是本类型的一个引用变量,且必须是引用。   当用一个已经初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝构造函数就会被自动调用,如果你没有自定义拷贝构造函数的时候,系统将会提供给一个默认的拷贝构造函数来完成这个过程,上面代码的复制核心语句就是通过Test(Test &c_t)拷贝构造函数内的p1=c_t.p1;语句完成的。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏康怀帅的专栏

PHP 面向对象

面向对象三大特性:封装、继承、多态。 官方文档:http://php.net/manual/zh/language.oop5.php 要创建一个类的实例,必须使...

2887
来自专栏Coding迪斯尼

自制Monkey语言编译器:实现函数闭包功能和为语言增加复杂数据结构

922
来自专栏九彩拼盘的叨叨叨

escape,encodeURI,encodeURIComponent

escape,encodeURI,encodeURIComponent这三个方法都是对URL进行编码的。

632
来自专栏happyJared

Python中的is和==以及字符串驻留机制

  先了解下官方文档中关于 is 和 == 的概念。is 表示的是对象标示符(object identity),而 == 表示的是相等(equality);is...

421
来自专栏大前端_Web

javascript事件监听中传递匿名函数(嵌套定义的命名函数)与命名函数的区别

版权声明:本文为吴孔云博客原创文章,转载请注明出处并带上链接,谢谢。 https://blog.csdn.net/wkyseo/articl...

884
来自专栏柠檬先生

JavaScript 基础(五) 函数 变量和作用域

函数定义和调用    定义函数,在JavaScript中,定义函数的方式如下:       function abs(x){         if...

1759
来自专栏我的小碗汤

Go语言中数组和切片笔记

今天有位大佬问我一个关于切片很简单的一个问题,却把我难住了,所以是时候了解下切片的底层了。

623
来自专栏前端知识分享

第83天:jQuery中操作form表单

注意:checked、selected、disabled要使用.prop()方法。

662
来自专栏coding for love

JS入门难点解析13-属性描述符,数据属性和访问器属性

(注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!) (注2:更多内容请查看我的目录。)

421
来自专栏Laoqi's Linux运维专列

python3–练习题

3185

扫码关注云+社区