淺拷貝和深拷貝的區別?


先考慮一種情況,對一個已知對象進行拷貝,編譯系統會自動調用一種構造函數——拷貝構造函數,如果用戶未定義拷貝構造函數,則會調用默認拷貝構造函數

//main.cpp

#include <iostream>
#include "student.h"
int main()
{
         Student s1;
         Student s2(s1);//Student s2 = s1;//復制對象

         return 0;
}
//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;
}

執行結果:調用一次構造函數,調用兩次析構函數,兩個對象的指針成員所指內存相同,這會導致什么問題呢?

 

name指針被分配一次內存,但是程序結束時該內存卻被釋放了兩次,會造成內存泄漏問題!

這是由於編譯系統在我們沒有自己定義拷貝構造函數時,會在拷貝對象時調用默認拷貝構造函數,進行的是淺拷貝!即對指針name拷貝后會出現兩個指針指向同一個內存空間。

 

所以,在對含有指針成員的對象進行拷貝時,必須要自己定義拷貝構造函數,使拷貝后的對象指針成員有自己的內存空間,即進行深拷貝,這樣就避免了內存泄漏發生。

 自己定義拷貝構造函數:

//student.h

#ifndef STUDENT_H
#define STUDENT_H
class Student
{
       private:
             int num;
             char *name;
      public:
              Student();//構造函數
               ~Student();//析構函數
               Student(const Student &s);//拷貝構造函數,const防止對象被改變
};

#endif

  

//student.cpp

#include "student.h"
#include <iostream>
#include <string.h>
using namespace std;

Student::Student()
{
      name = new char(20);
      cout << "Student " << endl;
}

Student::~Student()
{
         cout << "~Student " << (int)name << endl;
         delete name;
         name = NULL;
}

Student::Student(const Student &s)
{
         name = new char(20);
         memcpy(name, s.name, strlen(s.name));
         cout << "copy Student " << endl;
}

執行結果:調用一次構造函數,一次自定義拷貝構造函數,兩次析構函數。兩個對象的指針成員所指內存不同。

 

總結:淺拷貝只是對指針的拷貝,拷貝后兩個指針指向同一個內存空間,深拷貝不但對指針進行拷貝,而且對指針指向的內容進行拷貝,經深拷貝后的指針是指向兩個不同地址的指針。

再說幾句:

當對象中存在指針成員時,除了在復制對象時需要考慮自定義拷貝構造函數,還應該考慮以下兩種情形:

1.當函數的參數為對象時,實參傳遞給形參的實際上是實參的一個拷貝對象,系統自動通過拷貝構造函數實現;

2.當函數的返回值為一個對象時,該對象實際上是函數內對象的一個拷貝,用於返回函數調用處。

 

最后再留一個問題:對象的復制和賦值有什么區別?各自的應用場景是怎么樣的?

 

本文參考:

  1. http://blog.csdn.net/feitianxuxue/article/details/9275979
  2. 《C++程序設計-譚浩強》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM