浅拷贝与深拷贝概述
简单来说,浅拷贝就是在有指针的情况下,拷贝该指针,得到的新指针与原指针指向同一块内存;而深拷贝就是拷贝该指针,并申请一块新内存,使得新指针指向该新内存
采用深拷贝时不会出现在浅拷贝时重复释放指针造成内存泄漏的情况!!!
简单说明浅拷贝与深拷贝
- 如果用户未定义拷贝构造函数,则编译器会默认合成一个拷贝拷贝函数来完成构造(之后将在C++对象模型的学习中深入了解)
以一个简单的例子来说明:
//student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <iostream>
class student {
private:
int id_num;
char *name; //以该指针来体现浅拷贝与深拷贝
public:
student();
~student();
};
#endif /*STUDENT_H*/
//student.cpp
#include <iostream>
#include "student.h"
using namespace std;
student::student()
{
name = new char(20);
cout << "student()" << endl;
}
student::~student()
{
//取得char指针的地址采用(void*)
cout << "~student()" << (void*)name << endl;
delete name;
name = NULL;
}
//main.cpp
#include <iostream>
#include "student.h"
using namespace std;
int main()
{
student s1;
student s2(s1);
return 0;
}
在ubuntu下运行得到结果:
从上述结果可以get,调用构造函数只调用了一次,在delete name指针时析构了两次,而两个name指针指向相同的内存,这就是浅拷贝,会造成内存泄漏
(在前一个指针被析构时,内存已被释放,后续指针指向为空,造成内存泄漏)!!!
next
我们可以添加一个构造函数使之实现深拷贝:
//student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <iostream>
class student {
private:
int id_num;
char *name; //以该指针来体现浅拷贝与深拷贝
public:
student();
~student();
student(const student&);
};
#endif /*STUDENT_H*/
//student.cpp
#include <iostream>
#include <cstring>
#include "student.h"
using namespace std;
student::student()
{
name = new char(20);
cout << "student()" << endl;
}
student::~student()
{
cout << "~student()" << (void*)name << endl;
delete name;
name = NULL;
}
student::student(const student& a)
{
name = new char(20);
memcpy(name, a.name, strlen(a.name));
cout << "copy Student " << endl;
}
运行以上程序得到结果:
可以get,在构造时调用了自定义的构造函数,然后delete指针时调用了两次析构,从指针地址可以得出两个指针指向不同的内存,这样就不会造成内存泄漏,实现了深拷贝!
再次总结一下:浅拷贝只是对指针的简单拷贝,实际指向同一个内存;而深拷贝不仅拷贝指针,而且申请一块新空间给新指针,两个指针指向不同的内存
next
还有其余两种情形需要考虑调用拷贝构造函数:
- 当对象被当做参数交给某个函数时
- 当函数传回以一个类对象时
-----------------------------------get到知识点----------------------------------------------
- linux下C++多文件的编译
- 浅拷贝与深拷贝
- 输出一个char指针,用(void*)输出