C++ 浅拷贝、深拷贝、拷贝函数

无论是浅拷贝还是深拷贝,最重要的是考虑内存的变化,不同语言对不同变量的操作也许不同,但是归根结底是改变的只是内存。深拷贝是实实在在复制了一样的一份到内存中,而浅拷贝则类似于快捷方式。由于数据类型的不同,造成深浅拷贝的难点,下文内容可能与事实存在出入,当我完全理解后,会将这句话删除。

无法使用“变量是盒子”做解释,应该把变量视作便利贴。
——《流畅的python》(虽然是我在python书上看到的,但对于变量的理解是类似的)

1.C++篇

之前对浅拷贝和深拷贝的概念都有所模糊,当我看到“浅拷贝是简单的赋值操作”,或是“在类中调用了两次析构”,总是无法理解,今天就来好好盘一盘。
先来说一下总结,我最近终于想明白了:浅拷贝就是简单的值拷贝,如int i = 4类型,i在内存当中的值就是4,所以浅拷贝得到的也是4,但是如果是指针int *p = &i,p在内存当中存放的值是一个地址,那么拷贝得到的就是这个地址;然而深拷贝则是一个完全的复制。

1. 预备知识

看了大佬的博客,才发现要理解浅拷贝和深拷贝,首先要了解数据在内存中的存储方式,本文打算用最简单直白的方式陈述清其中的关系,若想了解详细,可看文末的参考链接。

基本类型和引用类型

基本类型:就像你跟你朋友路过你家,你跟你朋友说,这就是我家房子,你家房子的外观、家具,真真切切展现在你们面前。
引用类型(蕴含指针):就像你给你朋友一个你家的地址(和照片),你跟你朋友说这是我家,但是你得到哪哪哪才能看到我有哪些家具。

2. 浅拷贝

简单的赋值拷贝操作,但对于基本类型和引用类型存在不同的情况。

基本类型

赋的是数据,不存在深拷贝和浅拷贝的问题.
如:

    int x = 100;
    int y = x; //此时x和y都是100;

如果要改变y的值,x的值不会改变。

引用类型

赋的值地址(就是引用类型变量在内存中保存的内容)。
如:

	int* arr1 = new int[5]{1, 2, 3, 4, 5};
	int* arr2 = arr1;//这就是一个最简单的浅拷贝

改变arr2所引用的数据:arr2[0]=100时,那么arr1[0]的值也是100。

浅拷贝总结

在这里插入图片描述

3. 深拷贝

在堆区重新申请空间,进行拷贝操作。

// 拷贝构造函数实现
STRING( const STRING& s )
{
    //_str = s._str;
    _str = new char[strlen(s._str) + 1];  // 开辟一个新的内存空间
    strcpy_s( _str, strlen(s._str) + 1, s._str );  // 将旧值赋值在新内存空间上
}
STRING& operator=(const STRING& s)
{
    if (this != &s)  // 保证当前所指并非原对象
    {
        //this->_str = s._str;
        delete[] _str;
        this->_str = new char[strlen(s._str) + 1];
        strcpy_s(this->_str, strlen(s._str) + 1, s._str);
    }
    return *this;
}

4. 拷贝函数

参考链接

面试题:深拷贝和浅拷贝(超级详细,有内存图)
C++细节 深拷贝和浅拷贝(位拷贝)详解

2. 扩展python篇(矩阵拷贝)

np.copy其实是一个深拷贝。

import numpy as np

a = np.ones((2, 2))
print(a)
"""
[[1. 1.]
 [1. 1.]]
"""
print(id(a))  # id(a)获取变量的内存地址
"""
2433214758320
"""

# 浅拷贝(直接赋值)其实是对变量的直接引用-------------------------
b = a
print(b)
"""
[[1. 1.]
 [1. 1.]]
"""
b = np.append(b, [1, 1])
print(b, id(b))
"""
[1. 1. 1. 1. 1. 1.] 2433217421360
"""

# 深拷贝(np.copy):拷贝父对象,不会拷贝对象的内部的子对象------------
c = np.copy(a)  # 等价于 c = a.copy()
print(c)
"""
[[1. 1.]
 [1. 1.]]
"""
print(id(c))
"""
2433215549872
"""
c = np.concatenate((c, np.ones((3, 2)) * 2), axis=0)
c *= 2
print(c, id(c))
"""
[[2. 2.]
 [2. 2.]
 [4. 4.]
 [4. 4.]
 [4. 4.]] 2433214757648
"""
print(a, id(a))
"""
[[1. 1.]
 [1. 1.]] 2433214758320
"""

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

橙橙小狸猫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值