程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++ Primer筆記9_構造函數_拷貝構造(深拷貝與淺拷貝)

C++ Primer筆記9_構造函數_拷貝構造(深拷貝與淺拷貝)

編輯:C++入門知識

1.構造函數:


>構造函數是一個特殊的、與類同名的成員函數,用於給每個成員設置適當的初始值。

  1. >構造函數不能有返回值,函數名與類名相同。

  2. >缺省構造函數時,系統將自動調用該缺省構造函數初始化對象,缺省構造函數會將所有數據成員都初始化為零或 空。缺省構造函數是不帶參數的構造函數。

  3. >創建一個對象時,系統自動調用構造函數。


    構造函數的特點:

    1.構造函數可以重載,傳入什麼實參決定調用不同版本的構造函數。

    2.構造函數不能聲明為const 、也不能聲明為virtual;(析構函數可以)

    3.一個類如果自定義了一個構造函數,編譯器就不會生成默認構造函數。

    4.只有構造函數才有類似初始化列表的形式來初始化成員變量(特別是const成員變量只能在初始化列表中初始化)


    例子:

    #include 
    #include 
    
    class Person
    {
    public:
    	Person();//默認的構造函數
    	Person(int n, const string &str);//構造函數的重載
    private:
    	int age;
    	string *name;
    };
    
    


    2.拷貝構造


    先介紹一下深拷貝淺拷貝

    >淺拷貝: 指的是在對象復制時,只對對象中的數據成員進行簡單的賦值;默認拷貝構造函數執行的也是淺拷貝。 大多情況下“淺拷貝”已經能很好地工作了,但是一旦對象存在了動態成員,那麼淺拷貝就會出問題了。

    >深拷貝:當類的成員變量有指針類型時,拷貝對象時應該為指針變量重新分配好空間,避免淺拷貝中只拷貝指針的 值,使得兩個指針指向同一塊內存空間。


    淺拷貝缺陷例子:

    #include 
    #include 
    
    using namespace std;
    
    class Person
    {
    public:
    	Person();
    	Person(int n, const string &str);//構造函數重載
    	~Person();
    private:
    	int age;
    	string *name;
    };
    
    Person::Person():age(0), name(NULL)//構造函數初始化列表,定義時不必寫!
    {
    	cout << "Default Person" << endl;
    }
    
    Person::Person(int n, const string &str):age(n), name(new string(str))
    {
    	cout << "Init Person" << endl;
    }
    
    Person::~Person()
    {
    	if(name)
    	{
    		cout << "~Person " << "name: " << *name << " age: " << age << endl;
    	}
    	delete name;
    }
    
    int main()
    {
    	Person p1(10, string("SCOTT"));
    	Person p2 = p1;
    
    	return 0;
    }
    

    運行結果:

    Init Person
    ~Person name: SCOTT age: 10
    Segmentation fault (core dumped)

    程序崩潰原因:

    p2由p1初始化而得到,由於我們沒有自定義拷貝構造函數,所以調用的是默認的拷貝構造函數,屬於淺拷貝,只對name的值進行了拷貝;p1與p2中的name指針指向同一個new空間,最後調用析構函數時,會造成兩次delete而出現段錯誤。

    如下圖所示:

    \

    \


    解決方法:自定義拷貝構造函數! 達到深拷貝的效果

    深拷貝例子:<喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+PC9wPgo8cHJlIGNsYXNzPQ=="brush:java;">#include #include using namespace std; class Person { public: Person(); Person(int n, const string &str); Person(const Person &n); ~Person(); private: int age; string *name; }; Person::Person():age(0), name(NULL) { cout << "Default Person" << endl; } Person::Person(int n, const string &str):age(n), name(new string(str)) { cout << "Init Person" << endl; } //自定義拷貝構造函數 Person::Person(const Person &n) { if(n.name) { name = new string(*n.name); age = n.age; } } Person::~Person() { if(name) { cout << "~Person " << "name: " << *name << " age: " << age << endl; } delete name; } int main() { Person p1(10, string("SCOTT")); Person p2 = p1; return 0; }

    運行結果:

    Init Person

    ~Person name: SCOTT age: 10

    ~Person name: SCOTT age: 10
    沒有出現段錯誤,由此可見,上述解決方案可行。





  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved