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

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

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


 #include
<iostream>
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;
}
}; int main()
{
CExample
A();
CExample
B=A;
B.Show
();
return ;

当用一个已初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝构造函数就会被自动调用。也就是说,当类的对象需要拷贝时,拷贝构造函数将会被调用。以下情况都会调用拷贝构造函数:
(1)一个对象以值传递的方式传入函数体 
(2)一个对象以值传递的方式从函数返回 
(3)一个对象需要通过另外一个对象进行初始化。

如果在类中没有显式地声明一个拷贝构造函数,那么,编译器将会自动生成一个默认的拷贝构造函数,该构造函数完成对象之间的位拷贝。位拷贝又称浅拷贝,后面将进行说明。

自定义拷贝构造函数是一种良好的编程风格,它可以阻止编译器形成默认的拷贝构造函数,提高源码效率。

浅拷贝和深拷贝

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

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

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

来总结一下关于 深拷贝与浅拷贝需要知道的基本概念和知识:

(1)什么时候用到拷贝函数?

  a.一个对象以值传递的方式传入函数体; 
  b.一个对象以值传递的方式从函数返回;
  c.一个对象需要通过另外一个对象进行初始化。

如果在类中没有显式地声明一个拷贝构造函数,那么,编译器将会自动生成一个默认的拷贝构造函数,该构造函数完成对象之间的位拷贝。位拷贝又称浅拷贝

(2)是否应该自定义拷贝函数?

自定义拷贝构造函数是一种良好的编程风格,它可以阻止编译器形成默认的拷贝构造函数,提高源码效率。

(3)什么叫深拷贝?什么是浅拷贝?两者异同?

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

(4)深拷贝好还是浅拷贝好?

如果实行位拷贝,也就是把对象里的值完全复制给另一个对象,如A=B。这时,如果B中有一个成员变量指针已经申请了内存,那A中的那个成员变量也指向同一块内存。这就出现了问题:当B把内存释放了(如:析构),这时A内的指针就是野指针了,出现运行错误。

C++的深拷贝与浅拷贝的更多相关文章

  1. C#设计模式:原型模式(Prototype)及深拷贝、浅拷贝

    原型模式(Prototype) 定义: 原型模式:用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象.被复制的实例被称为原型,这个原型是可定制的. Prototype Pattern也是一 ...

  2. Objective-C中的深拷贝和浅拷贝

    在Objective-C中对象之间的拷贝分为浅拷贝和深拷贝.说白了,对非容器类的浅拷贝就是拷贝对象的地址,对象里面存的内容仍然是一份,没有新的内存被分配.对非容器类的深拷贝就是重写分配一块内存,然后把 ...

  3. $.extend()的深拷贝和浅拷贝详细讲解

    版权声明:作者原创,转载请注明出处! 语法:jQuery.extend( [deep ], target, object1 [, objectN ] ) 描述: 将两个或更多对象的内容合并到第一个对象 ...

  4. JavaScript中面向对象的的深拷贝和浅拷贝

    理解深拷贝和浅拷贝之前需要弄懂一些基础概念,内存中存储的变量类型分为值类型和引用类型. 1.值类型赋值的存储特点, 将变量内的数据全部拷贝一份, 存储给新的变量. 例如:var num = 123 : ...

  5. C++深拷贝与浅拷贝

    当用一个已初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝构造函数就会被自动调用.也就是说,当类的对象需要拷贝时,拷贝构造函数将会被调用.以下情况都会调用拷贝构造函数: (1)一个对 ...

  6. Python赋值语句与深拷贝、浅拷贝的区别

    参考:http://stackoverflow.com/questions/17246693/what-exactly-is-the-difference-between-shallow-copy-d ...

  7. [C#进阶系列]专题一:深入解析深拷贝和浅拷贝

    一.前言 这个星期参加了一个面试,面试中问到深浅拷贝的区别,然后我就简单了讲述了它们的之间的区别,然后面试官又继续问,如何实现一个深拷贝呢?当时只回答回答了一种方式,就是使用反射,然后面试官提示还可以 ...

  8. 也来玩玩 javascript对象深拷贝,浅拷贝

    经常看到讨论c#深拷贝,浅拷贝的博客,最近js写的比较多, 所以也来玩玩js的对象拷贝. 下面是维基百科对深浅拷贝的解释: 浅拷贝 One method of copying an object is ...

  9. OC中的深拷贝与浅拷贝

    深拷贝(deep copy)与浅拷贝(shallow copy)的定义一直是有争论的. 一种理解是: 所谓的浅拷贝, 就是不完全的拷贝 NSString *s = @"123"; ...

随机推荐

  1. ie8 window.open导出文件报错

    js创建一个<a>元素hiddenElementhiddenElement.setAttribute('href','')hiddenElement.setAttribute('targe ...

  2. AVLTree 平衡树

    //测试数据//第一组:7个输入,测试LL型,40,36,44,32,38,28,24://第二组:7个输入,测试RR型,40,36,44,43,48,52,56://第三组:7个输入,测试LR型,4 ...

  3. hihoCoder#1000

    刚开始学习C语言,准备在做hiho的题目的过程中来学习,在此进行记录,如果代码中有错误或者不当的地方还请指正.   时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 求两个整 ...

  4. Jacoco入门

    Jacoco介绍 转自:wangmuming 的博客 Jacoco是一个开源的覆盖率工具.Jacoco可以嵌入到Ant .Maven中,并提供了EclEmma Eclipse插件,也可以使用JavaA ...

  5. 关于.NET 的邮件发送类

    .NET 类库中已经有现成的封好的类库了,只要引用System.Net.Mail命名空间即可实现发邮件的功能 以下是代码 public class SendMail { private string ...

  6. .net core 学习笔记(1)-分页控件的使用

    最近有个小项目,用.net core开发练练手,碰到的第一个问题就是分页控件的问题,自己写太费时间,上网查了下,发现有人已经封装好了的,就拿过来用了,分页控件github:https://github ...

  7. js zTree的用法

    代码如下: <script type="text/javascript">    var reginTree = {    setting: {        view ...

  8. article和section

    article和section都是指页面中的块,但是article更加强调独立性,而section常被用来分块. section使用禁忌: 1.不要把section当作定义样式的容器,因为那是div的 ...

  9. SQL Server 2005 处理交叉表

    假设有一个表如下: 日期 时间 售货金额 2006-01-02 早上 50 2006-01-02 中午 20 2006-01-02  晚上 30 2006-01-02 零晨 40 2006-01-03 ...

  10. OpenCV阶段总结扩充。

    Mat类型简单介绍 /* cv::Mat类是用于保存图像以及其他矩阵的数据结构.默认情况下,其尺寸为0,我们也可以设置其初始尺寸,比如定义一个Mat类的对象,就要写cv::Mat pic(320,64 ...