C++拷贝构造函数:浅拷贝与深拷贝

  在介绍C++浅拷贝与深拷贝之前,我们先引出C++的拷贝构造函数。

  C++拷贝构造函数是一种特殊的构造函数,其形参是本类对象的引用。用于在建立一个新的对象时,使用一个已经存在的对象来初始化这个新对象。因为拷贝构造函数时特殊的构造函数,所以其没有返回值类型,且名称与类名相同;该函数只有一个参数,即此类对象的引用;所有类都必须有一个拷贝构造函数,如果没有自动以拷贝构造函数,系统会自动产生一个默认拷贝构造函数。

  自定义拷贝构造函数的一般形式为:

    类名::类名(const 类名& 对象名)

        {

          函数体;

        }

  浅拷贝:在进行初始化的过程中仅进行简单的数据成员赋值。

  例如:

    class A{

      private:

        int a;

      public:

        A(int ta):a(ta){}

    };

  有如下代码:

    A a(5);

    A b(a);

  程序执行b(a)时,执行操作:b.a=a.a;与系统自动产生的拷贝构造函数:

    A::A(const A& t){this->a=t.a;}

  执行相同内容。完整代码如下:

      

  执行结果为:

    

  从结果中我们发现,我们通过对象a初始化的对象b中,数据元素与a中完全相等,甚至指针指向的地址都相同。不难看出,在a初始化b过程中只是进行了简单的值传递,并没有为b中的p申请新的堆内存空间。即两个对象的指针指向同一个地址,这也就意味着此地址将被释放两次,显然是不可取的。这一点由输出结果中b中*p的值异常便可看出。为了解决此问题,我们需要深拷贝。

  深拷贝:当类中有指针类型元素,需要申请堆内存空间时,为新的指针分配新的内存空间。(不可进行简单的值传递)

  这时,需要我们自定义拷贝构造函数:

    

  此时,重新编译运行程序,结果为:

    

  此时,虽然对象a已被删除,对象a仍输出正常,这是因为在自定义的深拷贝函数中,为新的对象申请了新的空间,而不是令其指向a中p指针变量指向的地址。

  总结:

    当类中无需申请动态资源时,浅拷贝构造函数可以很好的工作。当需要申请动态内存时,即类中有指针变量,则需要自定义深度拷贝函数。

  表述不当之处,还望各路大神指正。

      

原文地址:https://www.cnblogs.com/SoundCoder/p/11135380.html

时间: 2024-08-13 01:39:21

C++拷贝构造函数:浅拷贝与深拷贝的相关文章

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

下面举一个简单的例子说明对象之间的拷贝(此例中没有自定义拷贝构造函数,在调用拷贝构造函数的时候,编译器会自动生成一个默认的拷贝构造函数,该构造函数完成对象之间的位拷贝)浅拷贝: #include<iostream> using namespace std; class CExample { private:int a; public: CExample(int b) { a=b; } void Show() { cout<<a<<endl; } }; int main(

c++语法:拷贝构造函数(深拷贝浅拷贝)

以拷贝的方式初始化对象 初始化对象时会调用构造函数,不同的初始化方式会调用不同的构造函数: 如果用传递进来的实参初始化对象,那么会调用普通的构造函数,我们不妨将此称为普通初始化: 如果用其它对象(现有对象)的数据来初始化对象,那么会调用拷贝构造函数,这就是以拷贝的方式初始化. 对于简单的类,默认的拷贝构造函数一般就够用了,我们也没有必要再显式地定义一个功能类似的拷贝构造函数.但是当类持有其它资源时,例如动态分配的内存.指向其他数据的指针等,默认的拷贝构造函数就不能拷贝这些资源了,我们必须显式地定

C++11 指针成员与拷贝构造(浅拷贝与深拷贝)

[1]浅拷贝 一直以来,设计一个类,个人认为,最能体现水平的地方在于:类中含有指针成员变量. 如下一个典型的浅拷贝示例: 1 #include <iostream> 2 using namespace std; 3 4 class HasPtrMem 5 { 6 public: 7 HasPtrMem() : d(new int(0)) 8 {} 9 ~HasPtrMem() 10 { 11 delete d; 12 d = nullptr; 13 } 14 15 int* d; 16 };

【OC学习-26】对象的浅拷贝和深拷贝——关键在于属性是否可被拷贝

对象的拷贝分为浅拷贝和深拷贝,浅拷贝就是只拷贝对象,但是属性不拷贝,拷贝出来的对象和原来的对象共用属性,即指向同一个属性地址,深拷贝则相当于不仅拷贝了一个对象还拷贝了它的属性,即完全是两个东西,只不过内容相同而已. 拷贝用到协议,如果这个类创建对象后,这个对象要被拷贝,那么这个类就需要用到拷贝协议,分两种:<NSCopying>和<NSMutableCopying>相当于一个是拷贝,另一个是拷贝后可修改. (1)浅拷贝的案例.有一个Person类,它创建一个person1对象后,用

拷贝构造函数的用法

1.拷贝构造函数是与类名相同,其形参是本类的对象的引用. 2.拷贝构造函数会在以下三种情况下被调用: 1).当用类的一个对象去初始化该类的另一个对象时. 2).如果函数的形参是类的对象,调用该函数,将对象作为函数实参传递给函数的形参时. 3).如果函数的返回值是类的对象,函数执行完成,将返回值返回时. 3.浅拷贝的失败例子: 1 #include <iostream> 2 #include <cstring> 3 4 using namespace std; 5 6 7 class

C++中拷贝构造函数

C++中拷贝构造函数 1.什么是拷贝构造函数: 拷贝构造函数嘛,当然就是拷贝和构造了.(其实很多名字,只要静下心来想一想,就真的是顾名思义呀)拷贝又称复制,因此拷贝构造函数又称复制构造函数.百度百科上是这样说的:拷贝构造函数,是一种特殊的构造函数,它由编译器调用来完成一些基于同一类的其他对象的构建及初始化.其唯一的参数(对象的引用)是不可变的(const类型).此函数经常用在函数调用时用户定义类型的值传递及返回. 2.拷贝构造函数的形式 Class X { public: X(); X(cons

正确实现浅拷贝和深拷贝

为对象创建副本的技术称为拷贝(也叫克隆).我们将拷贝分为浅拷贝和深拷贝. 浅拷贝:将对象中的所有字段复制到新的对象(副本)中.其中,值类型字段的值被复制到副本中后,在副本中的修改不会影响到源对象对应的值.而引用类型的字段被复制到副本中的是引用类型的引用,而不是引用的对象,在副本中对引用类型的字段值做修改会影响到源对象本身. 深拷贝:同样,将对象中的所有字段复制到新的对象中.不过,无论是对象的值类型字段,还是引用类型字段,都会被重新创建并赋值,对于副本的修改,不会影响到源对象本身. 无论是浅拷贝还

编写高质量代码改善C#程序的157个建议——建议14: 正确实现浅拷贝和深拷贝

建议14: 正确实现浅拷贝和深拷贝 为对象创建副本的技术称为拷贝(也叫克隆).我们将拷贝分为浅拷贝和深拷贝. 浅拷贝 将对象中的所有字段复制到新的对象(副本)中.其中,值类型字段的值被复制到副本中后,在副本中的修改不会影响到源对象对应的值.而引用类型的字段被复制到副本中的是引用类型的引用,而不是引用的对象,在副本中对引用类型的字段值做修改会影响到源对象本身. 深拷贝 同样,将对象中的所有字段复制到新的对象中.不过,无论是对象的值类型字段,还是引用类型字段,都会被重新创建并赋值,对于副本的修改,不

关于浅拷贝和深拷贝

说明:此文根据<编写高质量代码改善C#的57个建议>的建议14而写.在自己根据作者的思路进行代码练习的时候,感觉作者并未把定义说清楚全面,于是在定义中加入了自己的理解部分,如定义中的绿色字体部分. 为对象创建副本的技术成为拷贝(或叫克隆).我们将拷贝分为浅拷贝和深拷贝. 浅拷贝:将对象中的所有字段复制到新的对象(此对象为源对象的一个副本,即新对象)中.其中,值类型字段的值复制到副本中后,在副本中的修改不会影响源对象对应的值,在源对象中的修改不会影响到副本(新对象)对应的值.而引用类型的字段被复

c#中浅拷贝和深拷贝的理解

c#中拷贝有浅拷贝和深拷贝之分. 例如对象A,其中有值类型字段和引用类型字段: 1.浅拷贝: 对于值类型字段,直接逐位复制到新拷贝的副本对象中,修改副本的字段的值,不会影响源对象中字段的值: 对于引用类型字段,只复制字段的引用到副本对象中,引用的对象不复制,因为副本和源对象的字段引用的是同一个对象,所以修改副本对象中的字段会影响源对象. 实现:使用Object类MemberwiseClone实现. 2.深拷贝: 对于值类型字段,和浅拷贝的效果一样: 对于引用类型字段,不仅复制字段的引用到副本对象