2010-08-20 72 views
7

當你想從一個方法返回一個實例時,你是否創建了這個對象並且發回一個指針或者返回一個引用?這是什麼正確的方法和方法簽名?從函數返回指針或引用C++

+0

方法或函數。兩者不同,答案可能不同。 – 2010-08-20 20:39:37

+0

@Martin - 怎麼樣?你是否將成員函數稱爲方法和非成員函數作爲函數? – naivnomore 2010-08-20 20:45:42

+0

@naivnomore:是的(這是OO中的標準定義)。 – 2010-08-20 20:55:28

回答

8

在C++中有很多方法可以做到這一點。不幸的是,它們中的大多數導致混淆誰負責分配和釋放對象。有兩種方法,我推薦:

// Return a real object, automatic stack allocation. 
Foo GetFoo1() 
{ 
    Foo f; 
    // Init f. 
    return f; 
} 

// Use a smart, reference counted pointer that handles deallocation itself. 
boost::shared_ptr<Foo> GetFoo2() 
{ 
    boost::shared_ptr<Foo> f(new Foo); 
    // Init f 
    return f; 
} 
+0

我同意這條評論。應該注意的是,shared_ptr將其轉換爲TR1,並且在gcc和Visual Studio中都以std :: tr1 :: shared_ptr的形式實現。 unique_ptr應該注意,如果你有明確的「匯」和「來源」......但這在技術上是C++ 0x。如果你只使用C++ 98 ...你可以使用auto_ptr。但unique_ptr在各方面都優越。 – Dragontamer5788 2010-08-20 20:37:10

+0

對成員的引用如何(記住原始帖子是關於方法而不是函數)。 – 2010-08-20 20:38:00

+2

我不相信你可以返回對堆棧中分配的本地對象的引用。當你從GetFoo1返回時,f將超出範圍 – crazyx 2010-08-20 20:54:00

4

如果我創建一個純粹返回的實例,我會返回值作爲第一首選項。

只有當對象類型實際上不可複製時,我纔會考慮通過封裝所有權轉移的智能指針返回。

返回一個引用,我保留返回一個對象的引用,這個對象的所有權沒有被傳遞出該函數,也就是說它已經被其他東西所擁有,並且它的存在被保證,直到函數返回後的一個定義的時間。

2

如果您指的是Factory Method之類的東西,通常您會返回一個指針。更好的是,返回一個智能指針,並且不會因使用原始指針而創建更多的泄漏。

例子:

std::auto_ptr<Gizmo> MyFactory::CreateGizmo() 
{ 
    return new Gizmo; 
} 
6

無論是價值迴歸(人錯誤地認爲這是慢),或者,如果你返回一個多態型的覆蓋,在C返回一個auto_ptr(或更好的unique_ptr ++ 0x中)。

你不使用shared_ptr的原因是你永遠不能使你的指針離開它並使用不同的所有權語義。

永遠不會返回對本地實例的引用。

+0

雖然有點過時了,但在這裏有一個很好的Scott Meyers文章,這個答案在這裏:http://www.aristeia.com/Papers/resourceReturnProblem.txt – SCFrench 2010-08-20 20:41:06

0

這實際上取決於控制實例生命週期的實例範圍。如果這是一個本地實例,您可能會返回值,但會產生兩次構建對象的代價(除非您使用RVO)。另一種選擇是通過在函數內的堆中構造對象來返回指針。但是,使用這種方法,客戶端將負責刪除分配的內存,因此總是容易發生內存泄漏。這就是爲什麼你需要使用某種智能指針。 Anders Abel代碼通過代碼示例清楚地說明了上述兩種方法。順便說一句,你不能返回一個本地實例的引用,因爲一旦函數結束,實例將超出範圍。

6

答案取決於你在做什麼以及誰負責釋放。

第一種方法:在堆上分配並返回。曾經調用函數的人將負責刪除返回的指針。

​​

然後,在一些其他的功能

void functionThatNeedsObject() 
{ 
    SomeObject* obj = constructObject(); 
    //You must delete obj when done 
} 

第二種方法:返回一個參考。您必須注意不要通過返回本地或臨時變量超出範圍。

不這樣做:

int& DoubleValue(int nX) 
{ 
    int nValue = nX * 2; 
    return nValue; // return a reference to nValue here 
} // nValue goes out of scope here 

您可以返回作爲參數傳遞給函數的變量或者變量的引用。

SomeStruct& RefFunction(SomeStruct& nX, SomeStruct& nY) 
{ 
    return nX; 
} //nX is still in scope because it was passed to us