C++ 类的深拷贝和浅拷贝完美解决

//类的深拷贝和浅拷贝
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class Point{
public:
    Point(int _a,int _b,const char *pin/*in*/){
        x = _a;
        y = _b;
        remark = (char *)malloc(sizeof(char)*(strlen(pin) + 1));
        strcpy(remark, pin);
        cout << "我是自定义的有参构造函数4" << endl;
    }
    Point(Point &pm){
        cout << "我是自定义的拷贝构造函数3" << endl;
        //修改拷贝构造函数
        x = pm.x;
        y = pm.y;
        //remark = pm.remark; 这句话错误
        //修改后的方案
        remark = (char *)malloc(sizeof(char)*(strlen(pm.remark) + 1));
        strcpy(remark, pm.remark);
    }
    ~Point(){
        if (remark!=NULL)
        {
            free(remark);
        }
        cout << "我是自定义的析构函数2" << endl;
    }
    void GetPremark(){
        printf("指针变量remark的地址是%x\n", remark);
    }
    //BBB---运算符重载
    void operator=(Point &pm){
        //CCC  解决方案第三步
        if (remark!=NULL)
        {
            free(remark);
            remark = NULL;
        }
        //解决方案改良第二步(以下)
        x = pm.x;
        y = pm.y;
        remark = (char *)malloc(sizeof(char)*(strlen(pm.remark) + 1));
        strcpy(remark, pm.remark);
    }
private:
    int x;
    int y;
    char *remark;
};

void ProtectA(){
    Point p1(1, 1, "123");
    Point p2 = p1;
    printf("这是p1中字符指针的地址\n");
    p1.GetPremark();//打印  ad95e8
    printf("这是p2中字符指针的地址\n");
    p2.GetPremark();//打印  ad95e8
    //这说明类对象之间拷贝指针拷贝了指针变量的值(两个指针指向同一片内存),并没有新分配内存
    //出现问题:当先调用p2(函数的压栈,先定义后释放)的析构函数的时候,会释放指针变量remark指向的内存,
    //当调用p1的析构函数的时候就会报错

    //解决方案第一步--修改类的拷贝构造函数
    //BUG事例
    //Point p3;//报错  error C2512: “Point”: 没有合适的默认构造函数可用
    //这说明只要定义了有参构造函数,那么c++编译器就不会自动创建无参构造函数
    Point p4(2,3,"456");
    //赋值操作
    //p4 = p2;
    //分析:赋值操作会将p2的所有值(包括指针变量的值)拷贝到p4对象中
    //此时又会出现两个指针变量指向同一片内存的情况,当析构对象p4的时候,会释放指针变量指向的内存
    //那么析构p2的时候又会报错(那块内存已经被释放了,被释放了2次)

    //解决方案第二步--"="运算符重载
    //详情见 BBB  运算符重载的使用场景
    p4 = p2;

    //BUG事例
    p4 = p1;

    //分析:当执行p4 = p2; p4 = p1;仔细分析"="重载函数发现,p4 = p2;p4会开辟一块内存N1,
    //p4 = p1;p4会再开辟一块内存N2,此时N1这块内存永远不会被释放,这就造成了内存泄漏
    //为了解决这个问题  

    //解决方案第三步
    //我们可以在执行"="重载函数之前判断一下指针变量指向的内存又没有释放,
    //(所以要确定--定义对象的时候必须要分配指针变量的内存或者将指针变量置空)
    ///详情见 CCC
}

void main(){

    ProtectA();

    system("pause");
}

时间: 2024-08-27 02:06:46

C++ 类的深拷贝和浅拷贝完美解决的相关文章

c#中类的深拷贝和浅拷贝

### 类的深拷贝和浅拷贝 1. 若要深拷贝,当前类和引用的类都需要支持序列化 2. 扩展类的拷贝 3. 代码示例 ````C# using System.Runtime.Serialization.Formatters.Binary; using System.IO; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { List<DataTest> list = new List&

NSString,NSMutableString, NSArray ,NSMutableArray,NSDictionary,NSMutableDictionary 深拷贝,浅拷贝分析

NSString,NSMutableString, NSArray ,NSMutableArray,NSDictionary,NSMutableDictionary 深拷贝,浅拷贝. 首先我们得知道什么是深拷贝,什么事浅拷贝. 简单点说深拷贝就是拷贝内容,浅拷贝就是拷贝指针. 上面那些类我们可以这样理解他们的深.浅拷贝.只要上面那些类中的NSString,NSArray,NSDictionary这三个类的实例化对象是调用copy方法进行拷贝那么他们拷贝的就是一个指针,就是说他们只是拷贝了一个指向

从String类中看C++当中的深拷贝与浅拷贝解

了解过C++语言的人,都应该知道,C++语言中的构造函数,析构函数,拷贝构造函数,赋值运算符重载函数,如果不定义,编译器会自动生成的,当然,生成的只是一些最基本的,在达不到我们要求的条件下,就需要我们自己重新定义这些函数. 我们现在说的讲的是深拷贝与浅拷贝,当然讨论这个问题的基础,一般情况下是我们定义的变量是以指针形式出现的,原因就在于,不论赋值还是拷贝,我们要实现两个指针指向的内容一致,那我得到新的指针和原指针是指向同一块内存空间还是两块内存空间的相同内容.如果是指向同一块空间,就存在了安全隐

实现CMyString类--深拷贝与浅拷贝

实现CMyString类,实现赋值运算符函数(深拷贝与浅拷贝(写时拷贝)) 深拷贝:赋值运算符函数说明 步骤1.释放原来的内存空间 步骤2.再重新开辟要赋值的对象的大小的空间 步骤3.再将另一个对象的值拷贝给this对象 友元函数的说明:由于输出重载需要俩个参数,不能再隐含this指针,故使用友元函数 代码如下: <span style="font-size:18px;">class CMyString { public: CMyString() :str(new char

C++ Primer 学习笔记_20_类与数据抽象(6)_深拷贝与浅拷贝、空类与空数组

C++ Primer 学习笔记_20_类与数据抽象(6)_深拷贝与浅拷贝.空类与空数组 一.深拷贝与浅拷贝 浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换而言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象. 深拷贝:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量.那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象.换而言之,深拷贝把要复制的对象所引用的对象都复制了一遍. 浅拷贝可

探究JS中对象的深拷贝和浅拷贝

深拷贝和浅拷贝的区别 在讲深拷贝和浅拷贝的区别之前,回想一下我们平时拷贝一个对象时是怎么操作的?是不是像这样? var testObj1 = {a: 1, b:2}, testObj2=testObj1; testObj1.a = 7; console.log(testObj1); //{a: 7, b:2} console.log(testObj2); //{a: 7, b:2} 发现问题了吗?当testObj1变化时,testObj2相应的属性跟着变化了.这就是属于浅拷贝了,而所谓的深拷贝就

深拷贝与浅拷贝

一.浅拷贝和深拷贝 所谓浅拷贝,就是由默认的拷贝构造函数所实现的对数据成员逐一赋值.若类中含有指针类型的数据,这种方式只是简单的把指针的指向赋值给新成员,但并没有给新成员分配内存,因此这种方式必然会导致错误.为了解决浅拷贝出现的错误,必须显示的定义一个拷贝构造函数,使之不但复制数据成员,而且为对象分配各自的内存空间,这就是所谓的深拷贝. 二.浅拷贝 浅拷贝就是由默认的拷贝构造函数所实现的数据成员逐一赋值.通常默认的拷贝构造函数能够胜任这个工作,但是若类中含有指针类型的数据,这种数据成员逐一赋值的

【转】 c++拷贝构造函数(深拷贝,浅拷贝)详解

c++拷贝构造函数(深拷贝,浅拷贝)详解 2013-11-05 20:30:29 分类: C/C++ 原文地址:http://blog.chinaunix.net/uid-28977986-id-3977861.html 一.什么是拷贝构造函数      首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: int a=100; int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.  下面看一个类对象拷贝的简单例子. #include<iostream

c++拷贝构造函数(深拷贝,浅拷贝)详解

一.什么是拷贝构造函数      首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: int a=100; int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.  下面看一个类对象拷贝的简单例子. #include<iostream> using namespace std; class CExample { private: int a; public: //构造函数 CExample(int b) { a=b; printf("con