一、在OC中:
浅拷贝:浅拷贝就是对内存地址的复制,让目标对象指针和源对象指向同一片内存空间,当内存销毁的时候,指向这片内存的几个指针需要重新定义才可以使用,要不然会成为野指针。
A和B指向同一块浅拷贝就是拷贝指向原来对象的指针,使原对象的引用计数+1,可以理解为创建了一个指向原对象的新指针而已,并没有创建一个全新的对象。
深拷贝:深拷贝是指拷贝对象的具体内容,而内存地址是自主分配的,拷贝结束之后,两个对象虽然存的值是相同的,但是内存地址不一样,两个对象也互不影响,互不干涉。
深拷贝就是拷贝出和原来仅仅是值一样,但是内存地址完全不一样的新的对象,创建后和原对象没有任何关系。
总结:
1:可变对象的copy和mutableCopy方法都是深拷贝(区别完全深拷贝与单层深拷贝) 。
2:不可变对象的copy方法是浅拷贝,mutableCopy方法是深拷贝。
3:copy方法返回的对象都是不可变对象。
二、在C++中:
对一个已知对象进行拷贝,编译系统会自动调用一种构造函数——拷贝构造函数,如果用户未定义拷贝构造函数,则会调用默认拷贝构造函数。
//student.h
#ifndef STUDENT_H
#define STUDENT_H
class Student
{
private:
int num;
char *name;
public:
Student();
~Student();
};
#endif
//student.cpp
#include "student.h"
#include <iostream>
using namespace std;
Student::Student()
{
name = new char(20);
cout << "Student" << endl;
}
Student::~Student()
{
cout << "~Student " << (int)name << endl;
delete name;
name = NULL;
}
//main.cpp
#include <iostream>
#include "student.h"
int main()
{
Student s1;
Student s2(s1);//Student s2 = s1;//复制对象
return 0;
}
执行结果:调用一次构造函数,调用两次析构函数,两个对象的指针成员所指内存相同
name指针被分配一次内存,但是程序结束时该内存却被释放了两次,会造成内存泄漏问题!
这是由于编译系统在我们没有自己定义拷贝构造函数时,会在拷贝对象时调用默认拷贝构造函数,进行的是浅拷贝!即对指针name拷贝后会出现两个指针指向同一个内存空间。
所以,在对含有指针成员的对象进行拷贝时,必须要自己定义拷贝构造函数,使拷贝后的对象指针成员有自己的内存空间,即进行深拷贝,这样就避免了内存泄漏发生。
自己定义拷贝构造函数:
在student.h 申明拷贝构造函数 :
Student(constStudent &s);//拷贝构造函数,const防止对象被改变
在student.cpp 实现拷贝构造函数 :
Student::Student(constStudent &s)
{
name =newchar(20);
memcpy(name, s.name, strlen(s.name));
cout <<"copy Student "<< endl;
}
执行结果:调用一次构造函数,一次自定义拷贝构造函数,两次析构函数。两个对象的指针成员所指内存不同。
总结:浅拷贝只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。
再说几句:
当对象中存在指针成员时,除了在复制对象时需要考虑自定义拷贝构造函数,还应该考虑以下两种情形:
1.当函数的参数为对象时,实参传递给形参的实际上是实参的一个拷贝对象,系统自动通过拷贝构造函数实现;
2.当函数的返回值为一个对象时,该对象实际上是函数内对象的一个拷贝,用于返回函数调用处。
网友评论