浅拷贝与深拷贝

文章详细阐述了C++中类的初始化方式,特别是构造函数和拷贝构造函数的作用。重点讨论了深拷贝和浅拷贝的概念,以及它们在处理对象数据类型(如Array、Object)时的区别。浅拷贝仅复制对象的指针,而深拷贝则复制对象的内容到新的内存空间,确保对象独立。文章还提供了代码示例来演示深浅拷贝的实现和影响,并强调了在涉及内存管理时正确使用深拷贝的重要性。
摘要由CSDN通过智能技术生成

1 题目和参考链接

题目1链接
题目2链接
参考链接1

2 分析

初始化类有两种方式:函数名称均为类名

  1. 构造函数:参数是成员变量的输入值,没有返回值,作用是输入成员变量的初始值,赋值给成员变量,这是用变量值初始化类;
  2. 拷贝构造函数:参数是一个类,就是就是我们当前这个类,它的作用是用参数给的这个类的成员变量复制赋值给当前类的成员变量。拷贝又分为深拷贝、浅拷贝、赋值。

浅拷贝、深拷贝、赋值的区别

2.1 数据存储

数据分为:

  1. 基本数据类型(String, Number, Boolean, Null, Undefined,Symbol):真实的数据直接存储在栈(stack)中
  2. 对象数据类型(array、object):存储的是该对象在栈中引用,真实的数据存放在堆内存里。

引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。
在这里插入图片描述

2.2 区别

深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的。
深拷贝和浅拷贝的示意图大致如下:
在这里插入图片描述

  • 浅拷贝:会创建一个新对象,只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。
  • 深拷贝:会创造一个一模一样的新对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
  • 赋值:赋的其实是在栈中的地址,而不是堆中的数据。指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。

总结:
在这里插入图片描述

翻译一下:
普通数据类型的数据存在栈里,其他数据类型的是数据存储在堆中,栈中存储的是该数组在堆中地址。

  • 针对普通数据来说:
    • 赋值:指向栈中的数据
    • 浅拷贝和深拷贝没区别:新new一个对象,并将栈中数据拷贝一份赋值给新对象
  • 针对object array数据类型来说:
    • 浅拷贝:新new一个对象,只复制指向某个对象的指针。
    • 深拷贝:新new一个对象,将堆中的数据拷贝一份,新对象指向新开辟的内存。

2.3 实现

如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。拷贝构造函数的最常见形式如下:

classname (const classname &obj) {
   // 构造函数的主体
}

在这里,obj 是一个对象引用,该对象是用于初始化另一个对象的。

浅拷贝:直接赋值

        Person(const Person &p){//拷贝构造函数
        	this->name=p.name;
            this->age=p.age;
        }

深拷贝:先开辟新空间,再赋值

		Person(const Person& p){//拷贝构造函数   注意这里使用const防止被修改
            this->name=new char[strlen(p.name)+1];
            strcpy(this->name,p.name);
            this->age=p.age;
        }

总结

  1. 如果不想对象之间相互影响,一定要写深拷贝。
  2. 串引用的时候,规范写法,记得写const,避免无意识的修改不应修改的值。
  3. 开辟新空间的写法name = new type [size];

3 题目AC代码

#include <iostream>
#include <cstring>
#pragma warning(disable : 4996)
using namespace std;

class Person {
    public:
        char* name; // 姓名
        int age;    // 年龄

        Person(const char* name, int age) {
            this->name = new char[strlen(name) + 1];
            strcpy(this->name, name);
            this->age = age;
        }

        // write your code here......
        Person(const Person& p){//拷贝构造函数   注意这里使用const防止被修改
            this->name=new char[strlen(p.name)+1];
            strcpy(this->name,p.name);
            this->age=p.age;
        }

        void showPerson() {
            cout << name << " " << age << endl;
        }

        ~Person() {
            if (name != nullptr) {
                delete[] name;
                name = nullptr;
            }
        }

};

int main() {

    char name[100] = { 0 };
    int age;

    cin >> name;
    cin >> age;

    Person p1(name, age);
    Person p2 = p1;

    p2.showPerson();

    return 0;
}

4 验证深浅拷贝的code

  1. 创建对象p1,并赋值
  2. 拷贝p1p2,输出p2
  3. 修改p1,输出p2。(看p2会不会因为p1变了而变化)
#include <iostream>
#include <cstring>
#pragma warning(disable : 4996)
using namespace std;

class Person {
    public:
        char* name; // 姓名
        int age;    // 年龄

        Person(const char* name, int age) {
            this->name = new char[strlen(name) + 1];
            strcpy(this->name, name);
            this->age = age;
        }

        // write your code here......
        Person(const Person &p){//拷贝构造函数
        	//浅拷贝 
//        	this->name=p.name;
//            this->age=p.age;
            
            //深拷贝 
        	this->name = new char[strlen(p.name) + 1];
            strcpy(this->name, p.name);
            this->age=p.age;
        }

        void showPerson() {
            cout << name << " " << age << endl;
        }

        ~Person() {
            if (name != nullptr) {
                delete[] name;
                name = nullptr;
            }
        }

};

int main() {
    char name[100] = "1";
    int age=1;     
    Person p1(name, age);
    
    Person p2 = p1;//拷贝 
    p2.showPerson();//输出 
    
    p1.name[0]='2';//修改P1 
    p1.age=2;
    
    p2.showPerson();//输出 
    return 0;
}

浅拷贝:
在这里插入图片描述
深拷贝:
在这里插入图片描述

5 练习-数组类的深拷贝函数

class Array{
	private:
		int n;//数组大小 
		int *a;//数组 
	public:
		Array(){
			cin>>n;
			a=new int [n];
			for (int i=0;i<n;i++) cin>>a[i];
		}
		//my code
		Array(const Array &b){
			this->n=b.n;
			this->a=new int[this->n];//申请空间
			for(int i=0;i<this->n;i++){
				this->a[i]=b.a[i];
			}
		}
	//.....
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MORE_77

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值