C++深拷贝与浅拷贝的区别及应用

浅拷贝

只是对指针的拷贝,拷贝后两个指针指向同一个内存空间;

深拷贝

对指针指向的内容进行拷贝(重新分配内存),经深拷贝后的指针是指向不同地址的指针;

因此浅拷贝释放内存的时候很容易出现因为释放两个指针而内存出错。

浅拷贝(释放时,因为多次释放出错)

只拷贝指针

	//拷贝构造函数
	Vector(const Vector<T>& v)
		:_start(nullptr)
		,_finish(nullptr)
		,_endOfStorage(nullptr)
	{
		_start=v._start;
		_finish=v._finish;
		_endOfStorage=v._endOfStorage;
	}

深拷贝

对资源进行拷贝

 Vector(const Vector<T>& v)

		:_start(nullptr)
		, _finish(nullptr)
		, _endOfStorage(nullptr)
	{
		size_t n = v.capacity();
		_start = new T[n];
		for (size_t i = 0; i < v.size(); ++i)
		{
			_start[i] = v[i];
		}
		_finish = _start + v.size();
		_endOfStorage = _start + n;
	}

写一个Vector的类

 template<class T>
class Vector
{
typedef T* operator;
typedef const T* const_iterator;
	iterator _start;
	iterator _finish;
	iterator _endOfStorage;

 public:
//构造函数
 Vector()
		:_start(nullptr)
		, _finish(nullptr)
		, _endOfStorage(nullptr)
	{}

	//析构函数
	~Vector()
	{
		if(_start)
		{
			delete[] _start;
			_star=_finish=_endOfStorage=nullptr;
		}
	}
T& operator[](size_t pos)
	{
		if (pos >= 0 && pos < size())
			return _start[pos];
	}
size_t size() const
{
	return _finish - _start;
}

size_t capacity() const
{
	return _endOfStorage - _start;
}

};

可以用自己编辑器,把拷贝放进去试试;

附:c++深拷贝与浅拷贝问题实例

浅拷贝:简单的赋值拷贝操作;

深拷贝:在堆区重新申请空间,再进行拷贝操作;

问题:浅拷贝会带来堆区内存被重复释放的问题,析构函数被调用多次,导致程序运行崩溃;

解决:通过深拷贝解决,在堆区重新申请内存,各自释放自己的内存,避免重复释放;

#include <iostream>

using namespace std;

class Person
{
public:
    Person() {
        cout << "Person的默认构造函数调用"<<endl;
    }
    Person(int age,int height) {
        m_Age = age;
        m_Height = new int(height);//堆区重新申请空间,进行深拷贝,手动申请,手动释放;
        cout << "Person的有参函数调用" << endl;
    }
    int m_Age;
    int *m_Height;

    //自己实现拷贝构造函数,来避免编译器的拷贝构造函数造成浅拷贝问题;
    Person(const Person& p) {
        cout << "Person拷贝构造函数" << endl;
        m_Age = p.m_Age;
        //m_Height = p.m_Height; 浅拷贝,编译器默认实现这行代码;
        m_Height = new int(*p.m_Height);//深拷贝
    }

    ~Person() {
        //析构代码,将堆区开辟数据做释放操作
        if (m_Height != NULL) {
            delete m_Height;
            m_Height = NULL;
        }
        cout << "Person的析构函数调用" << endl;
    }
};

void test01(){
    Person p1(18,160);
    cout << "p1的年龄为:" << p1.m_Age<<"p1身高为:"<<*p1.m_Height<< endl;
    Person p2(p1);//编译器默认调用拷贝构造函数,进行浅拷贝操作
    cout << "p2的年龄为:" << p2.m_Age<< "p2身高为:"<<*p2.m_Height << endl;
}

int main(){
    test01();
    system("pause");
}

程序运行结果:

总结

到此这篇关于C++深拷贝与浅拷贝区别及应用的文章就介绍到这了,更多相关C++深拷贝与浅拷贝内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C/C++ 浅拷贝和深拷贝的实例详解

    C/C++ 浅拷贝和深拷贝的实例详解 深拷贝是指拷贝对象的具体内容,而内存地址是自主分配的,拷贝结束之后,两个对象虽然存的值是相同的,但是内存地址不一样,两个对象也互不影响,互不干涉. 浅拷贝就是对内存地址的复制,让目标对象指针和源对象指向同一片内存空间. 浅拷贝只是对对象的简单拷贝,让几个对象共用一片内存,当内存销毁的时候,指向这片内存的几个指针需要重新定义才可以使用,要不然会成为野指针. 在iOS开发中也会涉及到浅拷贝和深拷贝,简而言之: 浅拷贝:拷贝指针变量的值 深拷贝:拷贝指针所指向内存

  • C++浅拷贝与深拷贝及引用计数分析

    C++浅拷贝与深拷贝及引用计数分析 在C++开发中,经常遇到的一个问题就是与指针相关的内存管理问题,稍有不慎,就会造成内存泄露.内存破坏等严重的问题.不像Java一样,没有指针这个概念,所以也就不必担心与指针相关的一系列问题,但C++不同,从C语言沿袭下来的指针是其一大特点,我们常常要使用new/delete来动态管理内存,那么问题来了,特别是伴随着C++的继承机制,如野指针.无效指针使用.内存泄露.double free.堆碎片等等,这些问题就像地雷一样,一不小心就会踩那么几颗. 先来谈一下C

  • 详解C++中String类模拟实现以及深拷贝浅拷贝

    详解C++中String类模拟实现以及深拷贝浅拷贝 在C语言中/C++中,字符串是一个应用很广泛的类型,也是很基础的类型,C语言并没有直接处理字符串的操作而是采用字符指针和字符串数组进行操作,而在C++中标准库为我们封装了一个字符串的类供我们使用,使用需要#inlcude <string>头文件.我们也可以自己模拟实现一个简单的String类. 在模拟实现String类的过程中,不可避免的会遇到深拷贝浅拷贝的问题,下面就深拷贝浅拷贝做一个简介.所谓深拷贝浅拷贝,简单来说就是浅拷贝只是简单的将值

  • C++拷贝构造函数(深拷贝与浅拷贝)详解

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

  • Python的赋值、深拷贝与浅拷贝的区别详解

    在python中,给一个对象赋值,实际上就是对象对内存空间存储的值的引用.当我们把对象赋值给另一个变量的时候,这个变量并没有拷贝这个对象,而只是拷贝了这个对象的引用而已. 一般情况下我们会通过三种方法来实现拷贝对象的引用. Python直接赋值 直接赋值,默认浅拷贝传递对象的引用而已,原始列表改变,被赋值的变量也会做相同的改变.其实就是对'对象'的引用 示例: >>> list_demo = [2, 4, 6] >>> a = list_demo >>>

  • c# 深拷贝与浅拷贝的区别分析及实例

    深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响.举个例子,一个人名叫张三,后来用他克隆(假设法律允许)了另外一个人,叫李四,不管是张三缺胳膊少腿还是李四缺胳膊少腿都不会影响另外一个人.比较典型的就是Value(值)对象,如预定义类型Int32,Double,以及结构(struct),枚举(Enum)等. 浅拷贝是指源对象与拷贝对象共用一份实体,仅仅是引用的变量不同(名称不同).对其中任何一个对象的改动都会影响另外一个对象.举个例子,一个人一开始叫张三,后来

  • C++深拷贝与浅拷贝的区别及应用

    浅拷贝 只是对指针的拷贝,拷贝后两个指针指向同一个内存空间: 深拷贝 对指针指向的内容进行拷贝(重新分配内存),经深拷贝后的指针是指向不同地址的指针; 因此浅拷贝释放内存的时候很容易出现因为释放两个指针而内存出错. 浅拷贝(释放时,因为多次释放出错) 只拷贝指针 //拷贝构造函数 Vector(const Vector<T>& v) :_start(nullptr) ,_finish(nullptr) ,_endOfStorage(nullptr) { _start=v._start;

  • Python中深拷贝与浅拷贝的区别介绍

    首先,我们知道 Python 中有6个标准的数据类型,他们又分为可以变和不可变.不可变:Number(数字).String(字符串).Tuple(元组).可以变:List(列表).Dictionary(字典).Set(集合). 浅拷贝 改变原始对象中为可变类型的元素的值,会同时影响拷贝对象.改变原始对象中为不可变类型的元素的值,不会响拷贝对象. 代码演示 import copy #定义一个列表,其中第一个元素是可变类型. list1 = [[1,2], 'fei', 66]; #进行浅copy

  • 深入浅析Python中list的复制及深拷贝与浅拷贝

    在Python中,经常要对一个list进行复制.对于复制,自然的就有深拷贝与浅拷贝问题.深拷贝与浅拷贝的区别在于,当从原本的list复制出新的list之后,修改其中的任意一个是否会对另一个造成影响,即这两个list在内存中是否储存在同一个区域,这也是区分深拷贝与浅拷贝的重要依据.接下来我们就针对Python中list复制的几种方法,来探究一下其是属于深拷贝还是浅拷贝.弄清楚这个问题,有助于我们在编程中规避错误,减少不必要的调试时间. 一.非拷贝方法--直接赋值 如果用=直接赋值,是非拷贝方法.这

  • 详解Python直接赋值,深拷贝和浅拷贝

    直接赋值: 对象的引用,也就是给对象起别名 浅拷贝: 拷贝父对象,但是不会拷贝对象的内部的子对象. 深拷贝: 拷贝父对象. 以及其内部的子对象 在之前的文章中,提到可变对象和不可变对象,接下来也是以这两者的区别进行展开 直接赋值 对于可变对象和不可变对象,将一个变量直接赋值给另外一个变量,两者 id 值一致,其实本质上是将变量量绑定到对象的过程. >>> a=1 >>> b=a >>> id(a) == id(b) True >>>

  • Java的深拷贝与浅拷贝的几种实现方式

    1.介绍 关于Java的深拷贝和浅拷贝,简单来说就是创建一个和已知对象一模一样的对象.可能日常编码过程中用的不多,但是这是一个面试经常会问的问题,而且了解深拷贝和浅拷贝的原理,对于Java中的所谓值传递或者引用传递将会有更深的理解. 2.浅拷贝 浅拷贝就是获得拷贝对象的引用,而不是正真意义上的拷贝一个对象,例如 A a = new A(); A b = a; 此时引用变量a和b 同时指向了同一个堆中的内存空间,变量b只是复制了实例A的引用地址,并不是重新在堆中开辟了一个新的空间位置,来完整的复制

  • 一文带你了解JavaScript基础之深拷贝和浅拷贝

    目录 浅拷贝 深拷贝 补充 总结 拷贝(又名克隆,复制等),但是又分深拷贝和钱拷贝. 其实这个问题有时候想通了就很简单,如果想不通可能会有点绕,不过其难度比闭包等好理解的多. 为什么又这个概念的存在呢?先举一个例子. var person={ name:"张三", age:22 } var person1=person; console.log(person); console.log(person1); 似乎可以被拷贝下来了,但是如果你操作person1的属性值,这个时候person

  • python 中赋值,深拷贝,浅拷贝的区别

    目录 一.赋值实例 二.浅拷贝实例 三.深拷贝实例 赋值:其实就是对象的引用(相当于取别名). 浅拷贝(copy):拷贝父对象,不会拷贝对象内部的子对象,会引用子对象. 深拷贝(deepcopy): copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象. 一.赋值实例 # a这个大列表是一个父对象,里面的小列表是a的一个子对象 a = [1, 2, 3, ["a", "b"]] # 赋值实例 b = a print("a:", a

  • javascript深拷贝、浅拷贝和循环引用深入理解

    一.为什么有深拷贝和浅拷贝? 这个要从js中的数据类型说起,js中数据类型分为基本数据类型和引用数据类型. 基本类型值指的是那些保存在栈内存中的简单数据段,即这种值是完全保存在内存中的一个位置.包含Number,String,Boolean,Null,Undefined ,Symbol. 引用类型值指的是那些保存在堆内存中的对象,所以引用类型的值保存的是一个指针,这个指针指向存储在堆中的一个对象.除了上面的 6 种基本数据类型外,剩下的就是引用类型了,统称为 Object 类型.细分的话,有:O

随机推荐