1)如果类的成员变量都是基本数据类型,浅拷贝没有任何问题;
2)如果类的成员变量包含指针或者引用,那么对这个类的对象使用时就要注意了,浅拷贝只会拷贝指针或引用本身,而不会拷贝指针或引用所指向的对象,这样就会导致多个对象同时持有指向某个对象的指针,容易引发在释放该对象时,出现多次释放同一对象,或者内存泄漏。
看下如下例子:
class String {
public:
String(const char* str) {
cout << "String construct" << endl;
m_data = new char[strlen(str) + 1];
strcpy(m_data, str);
}
~String() {
cout << "String destroy" << endl;
delete[] m_data;
}
private:
char* m_data;
};
void main() {
vector<String> vec;
for (int i = 0; i < 1; i++) {
String str("hello");
vec.push_back(str);
}
cout << "end" << endl;
}
上述代码在main函数执行结束时会发生崩溃,原因是在for循环中,String str("hello")是局部的,而vec添加元素执行的是浅拷贝,此时str和vec中的对象都持有一个指针指向m_data;当for循环退出时,str会被释放,此时会调用String的析构函数,释放掉m_data,但是当main函数退出时,同样需要释放掉vec,vec中的对象就会被释放,由于该对象和str的指针都指向同一个m_data,所以会导致m_data的多次释放,从而引发崩溃。
image.png
可以看到String的析构函数被调用了两次。
当实现了String的拷贝构造函数就不会出现这个问题了
class String {
public:
String(const char* str) {
cout << "String construct" << endl;
m_data = new char[strlen(str) + 1];
strcpy(m_data, str);
}
String(const String& str) {
cout << "String copy construct" << endl;
m_data = new char[strlen(str.m_data) + 1];
strcpy(m_data, str.m_data);
}
~String() {
cout << "String destroy" << endl;
delete[] m_data;
}
private:
char* m_data;
};
当向vector中添加多个String时,会发现String的析构会被不断调用
void main() {
vector<String> vec;
for (int i = 0; i < 8; i++) {
String str("hello");
vec.push_back(str);
}
cout << "end" << endl;
getchar();
}
运行结果如下图:
image.png
参考:
https://toutiao.io/posts/410785/app_preview
http://blog.csdn.net/u012501459/article/details/44132147
网友评论