2017-08-04 38 views
1

我正在閱讀第二版C++:初學者指南作者:Herbert Schildt通過第一個對象在C++中創建第二個對象時,第一個對象的位置在哪裏?

模塊9.4,他談到返回對象:

就像對象可以傳遞給函數,函數可以返回的對象。要返回一個對象,首先聲明 該函數返回一個類的類型。其次,使用正常返回 聲明返回該類型的對象。以下程序有一個名爲mkBigger()的成員函數。它返回一個對象,其值爲調用對象的值的兩倍。

這是「下面的程序」,他提到:

// Returning objects. 
#include <iostream> 
using namespace std; 

class MyClass { 
int val; 
public: 
    // Normal Constructor. 
    MyClass(int i) { 
     val = i; 
     cout << "Inside constructor\n"; 
    } 

    ~MyClass() { 
    cout << "Destructing\n"; 
    } 

    int getval() { return val; } 

    // Return an object. 
    MyClass mkBigger() { 
     Myclass o(val * 2); // mkBigger() returns a MyClass object. 

     return o; 
    } 
}; 

void display(MyClass ob) 
{ 
    cout << ob.getval() << '\n'; 
} 

int main() 
{ 
    cout << " Before Constructing a.\n"; 
    MyClass a; 
    cout << "After constructing a.\n\n"; 

    cout << "Before call to display.\n"; 
    display(a); 
    cout << "After display() returns.\n\n"; 

    cout << "Before call to mkBigger().\n"; 
    a = a.mkBigger(); 
    cout << "After mkBigger() returns.\n\n"; 

    cout << "Before second call to display.\n"; 
    display(a); 
    cout << "After display() returns.\n\n"; 

    return 0; 
} 

這給了我們以下的輸出:

Before Constructing a. 
Inside constructor 
After constructing a. 

Before call to display. 
10 
Destructing 
After display() returns. 

Before call to mkBigger() 
Inside constructor 
Destructing 
Destructing 
After mkBigger() returns. 

Before second call to display. 
20 
Destructing 
After display() returns. 

Destructing 

Schildt然後繼續解釋說,原因有兩個「在mkBigger()調用期間「破壞」消息是因爲以下事實:

當函數返回一個對象時,會自動創建一個臨時對象,該臨時對象將保存返回值。這個對象實際上是由函數返回的。該值返回後,該對象被銷燬。

我真的很驚訝沒有'Destructing'消息。我遇到以下問題:給定mkBigger()的定義,將創建一個新的MyClass實例,並且該實例返回並放置在地址a中。因此,在做

a = a.mkBigger(); 

我的印象時,因此,原來的對象之前舉行一個一個不再引用。它是否正確?如果是這樣,那麼我有以下問題:

有人告訴我C++有一些垃圾收集的一些概念。這個物體會被垃圾收集嗎?這個對象現在在哪裏?這是許多人在談論C++的「危險」時提到的可能令人擔憂的內存泄漏的例子嗎?

+5

我強烈建議您從Schildt的作品中更好地學習C++。另外,如果你打算使用析構函數,你也應該使用複製構造函數和賦值運算符。 –

+1

如[這些]之一(https://stackoverflow.com/a/388282/6525260)也許? –

+0

我其實碰到很多人批評他的書,同時試圖找到我的問題的答案。我會尋找一本更好的書。 – Devilius

回答

3

mkbigger()中的一個析構函數在o上調用,MyClass實例通過值傳入;它在函數結束時超出了範圍。另一個是在o被銷燬時返回的臨時副本。還有什麼不在範圍之內?不是a in main();因此你不應該期望第三個析構函數被調用。自動對象超出範圍時,C++不會在調用析構函數之外提供垃圾回收。

與其他一些現代語言不同,a不「持有對象的引用」; a的對象,因爲它是一定數量的字節保存原始數據成員。當您執行a = a.mkBigger();時,MyClass的默認賦值運算符被調用,該運算符僅將右側臨時對象內的val複製到a中的val,覆蓋已存在的值。如果val是公開的,則a = a.makeBigger()將等於a.val = a.makeBigger().val

當您使用new分配內存,然後無法使用delete取消分配該內存時,會發生內存泄漏。對於內部執行此操作的類,您必須至少編寫自己的拷貝構造函數,賦值操作符和析構函數。

+0

Ahhhh,這使得很多意義。非常感謝你! – Devilius

相關問題