2013-03-26 147 views
-1

可以說我有一個變量指向我創建的對象。對於這個例子,可以說我有一個代表一張卡片的對象,該卡片有兩個成員 - 排名和套裝。從函數返回一個對象C++

接下來,可以說我初始化了我製作的物體結構,所以我現在有了一個擁有等級和套裝的卡物。

我的問題是什麼,如果我想返回,我創建了這個卡對象的函數: 我想要做這樣的事情:

Card* playerCard = foo() 

我知道玩家卡指向卡對象,所以不這意味着foo()也必須返回一個卡片對象?還有另一種解決這個問題的方法嗎?

基本上我想我的功能來生成卡,並且playerCard應該等於生成的卡。我不知道返回一個對象是否是最直接的解決方案,這就是爲什麼我也問是否有其他解決方案。

感謝您的幫助!

+4

我不確定你的所有要求,但我認爲返回'Card',而不是'Card *',應該沒問題。 – juanchopanza 2013-03-26 21:17:38

回答

7

我將逐漸從不良到好的方法。

首先,這是錯誤的方式做到這一點:

Card* foo() { 
    Card c; 
    return &c; 
} 

絕對不會這麼做。 Cardc將在foo的末尾銷燬,因此您返回的指針將指向無效的對象。

可以做到這一點:

Card* foo() { 
    return new Card(); 
} 

創建該卡由new Card()具有動態存儲持續時間,所以它不是在foo結束時被銷燬。因此返回的指針仍然指向該卡。然後你可以使用指針並且安全。

但是,這有另一個缺點。對於調用foo的人不明確,但他們現在負責對指針返回delete,以確保沒有內存泄漏。相反,它是最好用智能指針清晰地傳遞所有權給調用者:

std::unique_ptr<Card> foo() { 
    return std::unique_ptr<Card>(new Card()); 
} 

然而,更妙的是,如果你不需要動態分配的。爲什麼不只是返回Card,並讓它被複製出功能?你能做到像這樣:

Card foo() { 
    return Card(); 
} 

然後,而不是分配給一個指針,你會調用該函數,像這樣:

Card c = foo(); 

這當然取決於你的要求,從而令此。如果要以多態方式使用Card*,則需要使用其中一種指針方法。否則,您最終會切分您的衍生品Card

+0

+1。你今天不可阻擋;) – 2013-03-26 21:27:02

+0

「爲什麼不只是退還'卡'?」因爲你可能想從'Card'繼承,在這種情況下,你有很大的切片危險。 – 2013-03-26 21:31:27

+0

@MattPhillips當然,這就是我問的原因。 :D – 2013-03-26 21:32:19

0

,如果你想返回一個指針,您可以使用動態內存分配,否則你的指針會的foo執行後指向什麼(見Dangling pointers):

Card* foo() { 
    Card* ret = new Card(...); 
    ... 
    return ret; 
} 

上述代碼的另一個版本將使用std::unique_ptr從標準庫中清除給你的代碼的客戶端程序員,你正在返回一個動態分配的指針。它是一個智能指針,因此它會在其作用域的末尾自動釋放自己(不在函數結尾,因爲它被複制到調用塊)。

否則,如果你的對象/結構也不是很貴複製,你可以通過值導致複製返回它提出:

Card foo() { 
    Card ret(...); 
    ... 
    return ret; 
} 
+0

該副本很可能會在第二個代碼示例中消失,因此不應考慮複製的費用。 – juanchopanza 2013-03-26 21:24:57

+0

@juanchopanza,它真的取決於具體編譯器的實現,不是嗎? – Shoe 2013-03-26 21:26:12

+0

是的,它的確如此,但是很難找到那些近期沒有這樣做的人。 – juanchopanza 2013-03-26 21:27:15

0

如果函數foo()返回一個指向一個卡對象是已創建,分配一個卡指針,它應該工作得很好。重要的是要記住,你有效地通過它相同的卡雖然,不是副本或任何東西。

1

你正在返回一個指向對象的指針,而不是對象。

我不知道這裏你的問題是什麼,所以我就只給你一個完整的例子:

struct card {int rank; int suit}; 

card make_a_card() { 
    return card{10,3}; 
} 

int main() { 
    card a_card = make_a_card(); 
    // a_card == card{10,3} 
} 

你很少想從一個函數返回原始指針。對速度沒有必要(事實上,由於RVO和移動語義,實際上它最終會變得更慢),所以除了運行時多態性(即工廠方法)之外,沒有什麼理由要這樣做。