谈谈深拷贝与浅拷贝

2018-12-24  本文已影响0人  糖糖uzi

一、在OC中:

浅拷贝:浅拷贝就是对内存地址的复制,让目标对象指针和源对象指向同一片内存空间,当内存销毁的时候,指向这片内存的几个指针需要重新定义才可以使用,要不然会成为野指针。

A和B指向同一块

浅拷贝就是拷贝指向原来对象的指针,使原对象的引用计数+1,可以理解为创建了一个指向原对象的新指针而已,并没有创建一个全新的对象。

深拷贝:深拷贝是指拷贝对象的具体内容,而内存地址是自主分配的,拷贝结束之后,两个对象虽然存的值是相同的,但是内存地址不一样,两个对象也互不影响,互不干涉。

A和B指向各自的内存

深拷贝就是拷贝出和原来仅仅是值一样,但是内存地址完全不一样的新的对象,创建后和原对象没有任何关系。

总结:

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.当函数的返回值为一个对象时,该对象实际上是函数内对象的一个拷贝,用于返回函数调用处。

上一篇 下一篇

猜你喜欢

热点阅读