C++浅拷贝与深拷贝

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

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

        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;
	}
	~Person() {
	if (m_height != NULL) {
			delete m_height;
			m_height = NULL;
		}
		cout << "Person析构函数的调用" << endl;
	}
	int m_age;	//年龄
	int* m_height;	//体重
};

void test01(void) {
	Person p1(18,160);
	cout << "p1的年龄是" << p1.m_age << "体重是" << *p1.m_height << endl;
	Person p2(p1);
	cout << "p2的年龄是" << p2.m_age << "体重是" << *p2.m_height << endl;

}
int main(void)
{
	test01();

	system("pause");
	return 0;
}

        可以看出在test01()函数中先调用有参构造函数定义了对象p1,再调用拷贝构造函数将p1的数据复制给p2。代码看似没有错误,运行可以看到结果如下:

       可以发现程序运行出现了一个异常,这是什么原因呢?

        这是由于编译系统在我们没有自己定义拷贝构造函数时,会在拷贝对象时调用默认拷贝构造函数,进行的是浅拷贝!即对指针拷贝后会出现两个指针指向同一个内存空间。

        由于栈区的规则是先进后出,当执行完拷贝构造函数的时候,就会执行p2的析构函数,导致释放堆区开辟的数据。因此当执行p1的析构函数时就会导致内存释放2次,程序崩溃。

        所以,在对含有指针成员的对象进行拷贝时,必须自己定义拷贝构造函数,达到深拷贝的目的,才能必变内存重复释放。

增加拷贝构造函数后的代码:

#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;
	}
	//拷贝构造函数  
	Person(const Person& p) {
		cout << "Person拷贝构造函数!" << endl;
		//如果不利用深拷贝在堆区创建新内存,会导致浅拷贝带来的重复释放堆区问题
		m_age = p.m_age;
		m_height = new int(*p.m_height);
	}
	~Person() {
		if (m_height != NULL) {
			delete m_height;
			m_height = NULL;
		}
		cout << "Person析构函数的调用" << endl;
	}
	int m_age;	//年龄
	int* m_height;	//体重
};

void test01(void) {
	Person p1(18,160);
	cout << "p1的年龄是" << p1.m_age << "体重是" << *p1.m_height << endl;
	Person p2(p1);
	cout << "p2的年龄是" << p2.m_age << "体重是" << *p2.m_height << endl;

}
int main(void)
{
	test01();

	system("pause");
	return 0;
}

即在堆区重新开辟一片内存保存数据,这样就可以避免内存重复释放!!!

 

 

 

  • 54
    点赞
  • 162
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
设计并实现一个动态整型数组类Vect,要求: (1)实现构造函数重载,可以根据指定的元素个数动态创建初始值为0的整型数组,或根据指定的内置整型数组动态创建整型数组。 (2)设计拷贝构造函数和析构函数,注意使用深拷贝。 (3)设计存取指定位置的数组元素的公有成员函数,并进行下标越界,若越界则输出“out of boundary”。 (4)设计获取数组元素个数的公有成员函数。 (5)设计用于输出数组元素的公有成员函数,元素之间以空格分隔,最后以换行符结束。 在main函数中按以下顺序操作: (1)根据内置的静态整型数组{1,2,3,4,5}构造数组对象v1,根据输入的整型数构造数组对象v2。 (2)调用Vect的成员函数依次输出v1和v2的所有元素。 (3)输入指定的下标及对应的整型数,设置数组对象v1的指定元素。 (4)根据数组对象v1拷贝构造数组对象v3。 (5)调用Vect的成员函数依次输出v1和v3的所有元素。 设计并实现一个动态整型数组类Vect,要求: (1)实现构造函数重载,可以根据指定的元素个数动态创建初始值为0的整型数组,或根据指定的内置整型数组动态创建整型数组。 (2)设计拷贝构造函数和析构函数,注意使用深拷贝。 (3)设计存取指定位置的数组元素的公有成员函数,并进行下标越界,若越界则输出“out of boundary”。 (4)设计获取数组元素个数的公有成员函数。 (5)设计用于输出数组元素的公有成员函数,元素之间以空格分隔,最后以换行符结束。 在main函数中按以下顺序操作: (1)根据内置的静态整型数组{1,2,3,4,5}构造数组对象v1,根据输入的整型数构造数组对象v2。 (2)调用Vect的成员函数依次输出v1和v2的所有元素。 (3)输入指定的下标及对应的整型数,设置数组对象v1的指定元素。 (4)根据数组对象v1拷贝构造数组对象v3。 (5)调用Vect的成员函数依次输出v1和v3的所有元素。
深拷贝浅拷贝C++中关于对象拷贝的概念。 浅拷贝是指将一个对象的值复制到另一个对象,这样两个对象将共享同一块内存。当其中一个对象修改了共享内存的值时,另一个对象也会受到影响。浅拷贝只是简单地复制了对象的成员变量的值,而没有复制指向动态分配内存的指针。 深拷贝是指将一个对象的值复制到另一个对象,但是两个对象拥有独立的内存空间。深拷贝会复制对象的所有成员变量,包括指向动态分配内存的指针。这样,当其中一个对象修改了自己的内存空间时,另一个对象不会受到影响。 下面是一个示例代码,演示了深拷贝浅拷贝的区别: ```cpp #include <iostream> class MyClass { public: int* data; // 构造函数 MyClass(int value) { data = new int; *data = value; } // 拷贝构造函数 MyClass(const MyClass& other) { data = new int; *data = *(other.data); } // 析构函数 ~MyClass() { delete data; } }; int main() { // 浅拷贝示例 MyClass obj1(10); MyClass obj2 = obj1; // 浅拷贝 std::cout << *obj1.data << std::endl; // 输出 10 std::cout << *obj2.data << std::endl; // 输出 10 *obj1.data = 20; std::cout << *obj1.data << std::endl; // 输出 20 std::cout << *obj2.data << std::endl; // 输出 20,因为共享同一块内存 // 深拷贝示例 MyClass obj3(30); MyClass obj4 = obj3; // 深拷贝 std::cout << *obj3.data << std::endl; // 输出 30 std::cout << *obj4.data << std::endl; // 输出 30 *obj3.data = 40; std::cout << *obj3.data << std::endl; // 输出 40 std::cout << *obj4.data << std::endl; // 输出 30,因为拥有独立的内存空间 return 0; } ``` 在上面的代码中,`MyClass`类有一个指向动态分配内存的指针`data`。在浅拷贝示例中,当`obj2`被赋值为`obj1`时,它们共享同一块内存,因此修改其中一个对象的`data`值会影响另一个对象。而在深拷贝示例中,当`obj4`被赋值为`obj3`时,它们拥有独立的内存空间,因此修改其中一个对象的`data`值不会影响另一个对象。 需要注意的是,在使用深拷贝时,需要自定义拷贝构造函数和析构函数来确保正确地复制和释放动态分配的内存。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值