關於對象的construct與destruct

大衛注:
今天整理Computer上的舊資料,偶然發現了兩篇不知什麼時候從網上下來的文章,談的是關於對象construct與destruct的問題,感覺作者講的不是太清楚,按其思想進行改寫後發佈於此.

對象的construct與destruct是C++中一個最基本的概念,雖然簡單,但其中有些特性也值得我們去關注,以便更好地加以利用,寫出有效而且高效的代碼.
先看一個程序,程序很簡單,只是添加了一些輸出信息讓它看起來內容有點多:
// Demonstrates returning a temporary object.
#include <iostream>
using namespace std;

// class to print construct/destruct information
class CDemo
{

public
:
    CDemo(const CDemo & rcd)
    {

        cout << "Copy constructor: " << &rcd << "->" << this << endl;
    }


    CDemo()
    {

        cout << "Default constructor: " << this << endl;
    }


    CDemo &operator=(const CDemo & rcd)
    {

        cout << "Assignment operator: " << &rcd << "->" << this << endl;
        return
 *this;
    }


    CDemo::~CDemo()
    {

        cout << "Destructor: " << this << endl;
    }
};


// demo function to use CDemo and trigger something under the hood
CDemo foo()
{

    cout << "In foo" << endl;
    CDemo cd;
    cout << "cd is: " << &cd << endl;
    // Return a copy of cd.
    return cd;
}


int
 main()
{

    // This code generates a temporary
    // object, which is copied
    // into cd2 using the assignment
    // operator.
    CDemo cd2;
    cd2 = foo();
    cout << "cd2 is: " << &cd2 << endl << endl;

    // This code generates the temporary
    // object directly in the location
    // of retval;
    CDemo cd1 = foo();
    cout << "cd1 is: " << &cd1 << endl << endl;

    const
 CDemo& rcd = foo();
    cout << "Return from main!" << endl;

    return
 0;
}

以下是程序的輸出:
Default constructor: 0012FF6C
In foo
Default constructor: 0012FEEC
cd is: 0012FEEC
Copy constructor: 0012FEEC->0012FF60
Destructor: 0012FEEC
Assignment operator: 0012FF60->0012FF6C
Destructor: 0012FF60
cd2 is: 0012FF6C

In foo
Default constructor: 0012FEEC
cd is: 0012FEEC
Copy constructor: 0012FEEC->0012FF70
Destructor: 0012FEEC
cd1 is: 0012FF70

In foo
Default constructor: 0012FEEC
cd is: 0012FEEC
Copy constructor: 0012FEEC->0012FF64
Destructor: 0012FEEC

Return from main!
Destructor: 0012FF64
Destructor: 0012FF6C
Destructor: 0012FF70

在上面的程序中的main函數中,我們以不同方式定義了兩個CDemo對象和一個CDemo對象的引用,顯然,由於使用的方式不同,上面的輸出存在較大的區別.
下面逐一對以上3組輸出進行分析,請注意輸出信息中的地址信息.
1.

CDemo cd2; // 默認構造
cd2 = foo(); // 依次經歷一次默認構造,一次拷貝構造(構造返回時的臨時對象),一次賦值
2.
CDemo cd1 = foo(); // 經歷了一次構造和一次拷貝構造過程,這裏好像不存在拷貝構造返回的臨時對象的過程,其實並非如此.由於編譯器的優化,對象被直接構造在了cd1的緩衝區上.
3.
const
 CDemo& rcd = foo(); // 這裏同樣也存在拷貝構造返回時的臨時對象的過程,但是,與1中不同的是,該臨時對象沒有馬上釋放,而是直到main函數返回時才釋放.這是爲什麼呢?其實,這是由const reference的特性導致的,C++標準規定,如果一個臨時對象被賦值給一個(常量)引用,這個臨時對象在這個(常量)引用的生命週期中將不能被銷燬(C++標準只規定了對const reference是這樣的,對於普通的reference,雖然可能也是如此,但並不安全).

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章