cpp_shallow_deep_copy - ShenYj/ShenYj.github.io GitHub Wiki
编译器默认的提供的拷贝是浅拷贝(shallow copy)
-
将一个对象中所有成员变量的值拷贝到另一个对象
-
如果某个成员变量是个指针,只会拷贝指针中存储的地址值,并不会拷贝指针指向的内存空间
-
可能会导致堆空间多次free的问题
#include <iostream> using namespace std; class Car { int m_price; char *m_name; public: /// 加上 const,在调用传参的时候,就可以直接传常量字符串了: new Car(100, “bmw”); /// 做为函数参数时(同样适用于const指针),const 可以接收 const 和非 const 实参 /// /// 当前示例: `char name[] = { 'b', 'm', 'w', '\0' };` 在函数栈空间, /// `Car *car = new Car(100, name);` 代表着 m_name存储的是 name数组的地址,这样会造成堆空间指向栈空间,是很危险的,会出现野指针 /// 所以安全起见,保证堆空间使用堆空间内存,申请新的堆空间内存,将 name的内容copy到堆空间来使用 Car(int price = 0, const char *name = NULL) :m_price(price) { if (name == NULL) return; /// 申请新的堆空间 /// 1. { } 保证初始化 /// 2. +1 是为了保证 \0 结尾标记 /// ps: c语言的字符串长度比实际长度大1, 有个 \0 的结束标志 m_name = new char[strlen(name) + 1]{ }; /// 拷贝字符串数据到新的堆空间 strcpy(m_name, name); } ~Car() { if (m_name == NULL) return; delete[] m_name; m_name = NULL: } void display() { cout << "price is " << m_price << ", name is " << m_name << endl; } }; int main() { /// 如果不做copy处理,会存在堆空间指向了栈空间 -> m_name 指向 name char name[] = { 'b', 'm', 'w', '\0' }; Car *car = new Car(100, name); /// 不会调用拷贝构造函数 /// car 和 car1 都指向相同的堆空间数据 "bwm": 只会拷贝指针中存储的地址值,并不会拷贝指针指向的内存空间 /// 会导致堆空间多次free的问题 /// 默认编译器提供的拷贝是浅拷贝,当存在指针时,又希望数据是独立的,就需要使用深拷贝来保证内存、数据安全 Car car1 = car; getchar(); return 0; }
内容拷贝
如果需要实现深拷贝(deep copy),就需要自定义拷贝构造函数
-
将指针类型的成员变量所指向的内存空间,拷贝到新的内存空间
class Car { int m_price; char *m_name; /// 深拷贝 void copy(const char *name = NULL) { if (name == NULL) return; /// 申请新的堆空间 /// { } 保证初始化,同时为了保证 char[] 以 0结尾 m_name = new char[strlen(name) + 1]{ }; /// 拷贝字符串数据到新的堆空间 strcpy(m_name, name); } public: Car(int price = 0, const char *name = NULL) :m_price(price) { copy(name); } Car(const Car &car) :m_price(car.price) { copy(car.m_name); } ~Car() { if (m_name == NULL) return; delete[] m_name; m_name = NULL: } void display() { cout << "price is " << m_price << ", name is " << m_name << endl; } }; int main() { Car car1(100, "bmw"); /// 利用拷贝构造函数实现深拷贝 Car car2 = car1; return 0; }