C++-03、浅拷贝、深拷贝

2022-07-28  本文已影响0人  喂_balabala
浅拷贝
#define _CRT_SECURE_NO_WARNINGS // strcpy运行会报错,支持

#include<iostream>
#include<string.h>
using namespace std;

class Student1
{
public:

    int age;
    char * name;

    Student1() { cout << "空参数构造函数" << endl; }

    Student1(char * name) :Student1(name, 99) { cout << "一个参数构造函数" << endl; }

    Student1(char * name, int age) { 
        cout << "二个参数构造函数" << endl;

        this->name = (char *) malloc(sizeof(char * ) * 10);
        strcpy(this->name, name);

        this->age = age;
    }

    ~Student1() {
        cout << "析构函数执行" << endl;

        free(this->name);
        this->name = NULL;
    }

    // 默认有一个拷贝构造函数 隐式的 我们看不见
    // Student(const Student & stu) {
        // stu 旧地址

        // this 新地址

        // s2 = 新地址
    // }
};

void mainT1() {
    // ① 情况分析
    // Student s1;
    // Student s2;
    // cout << &s1 << endl;
    // cout << &s2 << endl;
    // 两个地址 完全不同
    // 打印:
    // 空参数构造函数
    // 空参数构造函数
    // 1000H
    // 2000H


    // ② 情况分析 
    Student1 s1;
    Student1 s2 = s1; 

    // 两个地址 完全不同
    // 打印:
    // 空参数构造函数
    // 1000H
    // 2000H

    cout << &s1 << endl;
    cout << &s2 << endl;

    getchar(); // 不要一闪而过,让程序停留
}
浅拷贝重复释放空间的问题
#define _CRT_SECURE_NO_WARNINGS // strcpy运行会报错,支持

#include<iostream>
#include<string.h>
using namespace std;

class Student2
{
public:

    int age;
    char * name;

    Student2() { cout << "空参数构造函数" << endl; }

    Student2(char * name) :Student2(name, 99) {
        cout << "一个参数构造函数 this:" << this << endl;
    }

    Student2(char * name, int age) {
        cout << "二个参数构造函数 this:" << this << endl;

        this->name = (char *)malloc(sizeof(char *)* 10);
        strcpy(this->name, name);

        this->age = age;
    }

    ~Student2() {
        cout << "析构函数执行 &this->name:" << &this->name << endl;

        free(this->name);
        this->name = NULL;
    }

    // 默认有一个拷贝构造函数 隐式的 我们看不见
    
    // 一旦复写了拷贝构造函数,默认的还在吗? Java的构造函数一个思路  
    
    Student2(const Student2 & stu) {
        // stu 旧地址

        // this 新地址

        // s2 = 新地址

        cout << "拷贝构造函数 &stu:" << &stu << " this:" << this << endl;

        // 新地址.name = 旧地址.name (浅拷贝)
        this->name = stu.name;

    } // 此拷贝构造函数执行完 就会出现一个 this==新地址  给 main函数的 stu
};

Student2 getStudent(char * name) {
    Student2 stu(name); // 旧地址

    cout << "getStudent函数:" << &stu << endl; // 旧地址

    return stu; // stu 旧地址
} // 弹栈 释放 栈成员 stu

void mainT3() {
    // = 会执行拷贝构造函数
    // stu 新地址
    Student2 stu = getStudent("截拳道");

    cout << "main函数:" << &stu << endl;

    // 打印:
    // 两个参数构造函数
    // 一个参数构造函数
    // getStudent函数: 1000H地址
    // 拷贝构造函数 构建新地址 把新地址 给 main函数的 stu == 新地址
    // 析构函数
    // main函数: 

    // getchar(); // 不要一闪而过,让程序停留
} // main函数弹栈 stu 新地址 析构函数执行

// 伏笔一: main函数弹栈 stu 新地址 析构函数执行 会造成 重复释放空间的问题 
深拷贝
#define _CRT_SECURE_NO_WARNINGS // strcpy运行会报错,支持

#include<iostream>
#include<string.h>
using namespace std;

class Student
{
public:

    int age;
    char * name;

    Student() { cout << "空参数构造函数" << endl; }

    Student(char * name) :Student(name, 99) {
        cout << "一个参数构造函数 this:" << (int)this << endl;
    }

    Student(char * name, int age) {
        cout << "二个参数构造函数 this:" << (int)this << endl;

        this->name = (char *)malloc(sizeof(char *)* 10);
        strcpy(this->name, name);

        this->age = age;
    }

    ~Student() {
        cout << "析构函数执行 &this->name:" << (int)this->name << endl;

        free(this->name);
        this->name = NULL;
    }

    // 默认有一个拷贝构造函数 隐式的 我们看不见
    // 一旦复写了拷贝构造函数,默认的还在吗? Java的构造函数一个思路
    // 自定义拷贝构造函数 如果有堆成员,必须采用深拷贝
    Student(const Student & stu) {
        // stu 旧地址

        // this 新地址

        // s2 = 新地址

        cout << "拷贝构造函数 &stu:" << (int)&stu << " this:" << (int)this << endl;

        // 【浅拷贝】:新地址name  旧地址name 指向同一个空间,会造成,重复free的问题,引发奔溃
        // 新地址name = 旧地址name (浅拷贝)
        // this->name = stu.name;

        // 【深拷贝】
        
        this->name = (char *)malloc(sizeof(char *)* 10);
        
        strcpy(this->name, name);

        this->age = stu.age;

        cout << "拷贝构造函数2 this->name:" << ((int) this->name) << "  stu.name:" << (int)stu.name << endl;

    } // 此拷贝构造函数执行完 就会出现一个 this==新地址  给 main函数的 stu


    // 默认的拷贝构造函数 是浅拷贝
};

void showStudent(Student stu) {
    cout << "showStudent函数:" << (int)&stu << "  " << stu.name << "," << stu.age<< endl;
}

void main() {
    Student stu("刘奋", 31);

    //普通对象作为参数传递会触发拷贝构造函数
    showStudent(stu); // 弹栈后 新地址name释放一遍
    // showStudent(stu); // 弹栈后 新地址name释放一遍
    // 两次释放新地址name 会奔溃

    // 释放一次新地址name  再释放一次旧name也报错

    showStudent(stu);


    showStudent(stu);


    showStudent(stu);


    showStudent(stu);

    getchar();
} // main函数弹栈 stu 旧地址


// 专业技能:1.研究过C++语言深拷贝原理
上一篇下一篇

猜你喜欢

热点阅读