zoukankan      html  css  js  c++  java
  • 【C++基础 02】深拷贝和浅拷贝

    我的主题是,每天积累一点点。

    ===========================================


    在类定义中,如果没有提供自己的拷贝构造函数,则C++提供一个默认拷贝构造函数。

    C++提供的默认拷贝构造函数的工作方法是:完成一个成员一个成员的拷贝。如果成员是类对象,则调用其拷贝构造函数或者默认拷贝构造函数。需要注意的是,默认拷贝构造函数不会处理静态成员变量。

    简单的自定义拷贝构造函数:

    class Student{
    public:
    	//拷贝构造函数
    	Student(Student& s)
    	{
    		a = s.a;
    	}
    protected:
    	int a;
    };

    如上,我们拷贝的策略是一个一个成员的拷贝,但是如果一个类拥有资源,当其构造函数分配了一个资源(如堆内存),而拷贝构造函数没有去分配该资源,那么两个对象都拥有同一个资源,这称为浅拷贝。

    浅拷贝的一个问题是,当对象析构的时候,该资源将经历两次资源返还。比如下面这样子:


    class Person
    {
    public:
    	Person(char* pN)
    	{
    		cout<<"Constructing"<<pN<<endl;
    		pName = new char[strlen(pN) + 1];
    		if(pName != 0)
    		{
    			strcpy(pName,pN);
    		}
    	}
    	~Person()
    	{
    		cout<<"Destructing"<<pName<<endl;
    		delete pName;
    		pName = NULL;
    	}
    protected:
    	char* pName;
    };
    
    
    void main()
    {
    	Person p1("fzll");
    	Person p2 = p1;   //调用默认拷贝函数
    }
    
    //输出信息
    Constructing fzll
    Destructing fzll
    Destructing
    Null pointer assignment

    可以看到,第二次释放资源的时候,出错了。因为默认拷贝构造函数并没有分配新的资源。

    所以我们需要自定义拷贝构造函数,并分配资源,使拷贝和被拷贝的对象指向不同的资源,这就是深拷贝的概念。C++提供的默认拷贝构造函数就是浅拷贝。


    具体如下:

    class Person
    {
    public:
    	Person(char* pN)
    	{
    		cout<<"Constructing"<<pN<<endl;
    		pName = new char[strlen(pN) + 1];
    		if(pName != 0)
    		{
    			strcpy(pName,pN);
    		}
    	}
    	Person(Person& p)
    	{
    		cout<<"CopyPerson "<<p.pName<<endl;
    		pName = new char[strlen(p.pName) + 1];
    		if(pName != 0)
    		{
    			strcpy(pName,p.pName);
    		}
    
    	}
    	~Person()
    	{
    		cout<<"Destructing"<<pName<<endl;
    		delete pName;
    		pName = NULL;
    	}
    protected:
    	char* pName;
    };
    
    
    void main()
    {
    	Person p1("fzll");
    	Person p2 = p1;   //调用自定义拷贝函数
    }
    
    //输出信息
    Constructing fzll
    CopyPerson fzll
    Destructing fzll
    Destructing fzll

    堆内存是最常用的需要构造拷贝的资源,还有其它资源,比如文件的打开,设备的占有(如打印机)服务业需要深拷贝。


    一个很好的经验是:如果你的类需要析构函数来释放资源,那么它也需要一个拷贝构造函数(深拷贝的方式)。


    ==============================================================


    转载请注明出处:http://blog.csdn.net/shun_fzll/article/details/37774495



  • 相关阅读:
    Eric 的随机文件名 生成方法
    .NET模板引擎 EFPlatform.CodeGenerator (代码生成器 静态页生成 生成HTML 模板)
    Eric的行政区(省市)下列表控件和标签控件
    下载网页中远程图片的方法
    一起来玩Twister(扭扭乐)
    ASP.NET 安全认证(四)——巧妙实现 Form 表单认证跨站点、跨服务器的单点登录(Single Sign On) .
    DataList的编辑、更新、删除、全选、分页以及 <EditItemTemplate>模版中的DropDownList的数据绑定
    ASP.NET 安全认证(三)—— 用Form 表单认证实现单点登录(Single Sign On) .
    C# 中的委托和事件
    ASP.Net获取当前运行文件的文件名称
  • 原文地址:https://www.cnblogs.com/fzll/p/3954588.html
Copyright © 2011-2022 走看看