2013-04-11 151 views
0

我對C++中的範圍和內存管理有疑問。這是我遇到麻煩的情況:內存和範圍管理

Abc function f() 
{ 
    Abc c; 
    return c; 
} 

Abc d = f(); 
if(d) cout << "hi"; 

會說「hi」嗎?我的意思是...在f()中創建的Abc不是動態的(我們沒有寫一個新的)......但是我們正在返回值,所以我們獲得了對該對象的引用。它會有價值嗎?或者一旦它脫離了它的範圍,它就會死亡?

謝謝!

+1

你爲什麼不自己嘗試看看?如果在這裏撰寫和發佈問題,這會花費更少的時間。 – 2013-04-11 08:55:19

+0

另外,「我們正在返回值」 - 是的,「所以我們保留對對象的引用」 - false。我在這裏沒有看到參考。 – 2013-04-11 08:56:21

+1

只有在'Abc'可以轉換爲'bool'或者可以轉換爲bool的內建類型時纔會編譯。是這樣嗎? – juanchopanza 2013-04-11 08:58:06

回答

1
#include <iostream> 
using std::cout; 
using std::endl; 

class Abc 
{ 
    int m_value = 0; 
public: 
    Abc() 
    { 
     cout << "Default Constructor" << std::endl; 
    } 

    Abc(const Abc& _source) 
    { 
     cout << "Copy Constructor" << std::endl; 
     //copy stuff 
    } 

    Abc& operator=(const Abc& _source) 
    { 
     cout << "assignment operator" << std::endl; 
     if (this == &_source) 
      return *this; 
     //copy stuff 

     return *this; 
    } 

    Abc(const Abc&& _source) 
    { 
     cout << "Move Constructor" << std::endl; 
     //move stuff 
    } 

    Abc& operator=(const Abc&& _source) 
    { 
     cout << "move assignment operator" << std::endl; 
     //move stuff 
     return *this; 
    } 

    ~Abc() 
    { 
     cout << "Destructor"<< std::endl; 
    } 

    void setValue(int _value) 
    { 
     m_value = _value; 
    } 

    int getValue() 
    { 
     return m_value; 
    } 
}; 

Abc f() 
{ 
    Abc c; 
    c.setValue(100); 
    cout << "c value: " << c.getValue() << endl; 
    return c; 
} 

int main() 
{ 
    Abc d = f(); 
    cout << "d value: " << d.getValue() << endl; 
    d.setValue(200); 
    cout << "d value: " << d.getValue() << endl; 
} 

這裏是輸出:

默認構造

C值:100

d值:100

d值:200

析構

從這裏你可以看到,編譯器足夠聰明地重用分配的對象而不用做任何愚蠢的副本(C++ 98/03,C++ 11相同的輸出)。

編譯MinGW(GCC 4.7.1)。

0
Abc f() 
{ 
    Abc c; 
    return c; 
} 

創建Abc類型的c,複製和從函數返回(帶NRVO拷貝可以被消隱)。

Abc d = f(); 
if(d) cout << "hi"; 

創建d與功能f返回的值複製初始化。什麼是Abc類型?如果它有operator bool(或operator T(),其中T可以隱式轉換爲bool) - 可能會打印「嗨」。

1

你的情況是不可能作出確切的聲明,在下面的第二種情況:

Abc* function f() 
{ 
    Abc *c = new Abc();; 
    return c; 
} 

Abc* d = f(); 
if(d) cout << "hi"; 

是的,它會說「你好」,所不同的是,在第一種情況下,c是保存在堆棧中,而在第二種情況下保存在堆棧中。在你的情況下,鍵入if(d)不是一個很好的方法來檢查對象是否存在,因爲它是在棧中定義的。

爲了檢查你的情況,你可以添加一個日誌到Abc的析構函數,看它是否會被擊中。當你用f()返回對象時,你會觀察到Abc的析構函數被調用。但這並不意味着物體已經死亡。只有它的析構函數被調用。但在這種情況下,你不能正確使用析構函數。這是選擇指向對象的指針的原因之一,而不是直接定義它們的原因之一。