[英]Returning a pointer vs. passing a reference to an object to store the answer in C++
我對在這種特殊情況下使用指針還是引用有一個普遍的疑問。
假設我有一個函數,它將執行一些計算並將該值存儲在對象中,以供調用者以后使用。 我可以通過使用指針或引用來實現。
雖然,我更喜歡使用引用,因為我嘗試盡可能地避免使用指針,一種方法相對於另一種方法是否有優點/缺點。
使用指針的代碼如下:
Node*& computeNode() {
// Do some computation before creating a node object.
Node* newNode = new Node;
newNode->member1 = xyz;
newNode->member2 = abc;
// and so on ...
return newNode;
}
使用引用的代碼可以執行以下操作:
void computeNode(Node& newNode) {
// Do some computation before assigning values to the node object.
newNode.member1 = xyz;
newNode.member2 = abc;
// and so on.
}
我可以看到的差異如下:
使用指針方法時,newNode對象將在堆上分配。 因此,除非我對其調用delete,否則它不會被刪除。 但是,在引用方法中,是否在堆/堆棧上分配newNode取決於調用者創建newNode對象的操作。
每當我們使用引用時,傳遞給函數的參數數量至少增加1。這很好,只有我發現將返回對象也傳遞給函數調用有點反常理,除非我在函數中命名函數這種方式對於API用戶而言顯而易見。
通過使用引用,我可以模擬多個對象的返回。 在指針方法中,我認為我必須將所有對象包裝在另一個結構(如pair類)中,然后將其返回。 這增加了開銷。
但是,我不知道通常一個人是否比另一個人更可取。 並且如果C ++中有任何函數命名約定,使開發人員知道他應該將返回對象也作為參數傳遞。
您可以嘗試返回auto_ptr或shared_ptr。 這樣可以消除刪除問題。
第二種方法可能更可取,因為在您忘記delete
返回的指針的情況下,不會發生內存泄漏。
通常,以這樣一種方式進行編碼是一種好習慣,即分配堆內存的每個函數或對象也都會釋放該內存。 您的第一個示例違反了這種做法,這使函數調用者有責任重新分配內存。 這使內存泄漏的可能性更大,因為現在每次調用該函數時,都有另一個機會忘記刪除返回的指針。
在對象的大小不那么大的情況下,您可能還需要考慮按值返回對象(這將返回對象的副本)。 即使這需要創建一個副本,但如果對象不是很大,也不會影響性能。 (這種方法在將來會隨着C ++ 0x move語義變得更具吸引力。)
我認為您的第一個選擇應該是按值返回(或者讓構造函數計算成員?):
Node computeNode()
{
Node n;
n.x = abc;
n.y = xyz;
return n;
}
這看起來效率低下,但是很有可能使用NRVO消除了復制。
如果仍然需要動態分配Node,則應按值返回指針(指針的副本):
Node* computeNode();
否則,您將返回對局部變量(指針)的引用。
我更喜歡使用第二種方法發送回信息(如您所說,無需使用額外的結構即可進行多次“返回”),並且通常返回錯誤或成功代碼 。
另外,我將純輸入參數設置為const &
以區分輸入變量和輸出變量。
您可以通過使用const引用按值返回並在某些情況下避免復制:
Node computeNode() {
// Do some computation before creating a node object.
Node newNode;
newNode.member1 = xyz;
newNode.member2 = abc;
return newNode;
}
const Node &n = computeNode();
臨時對象在computeNode中的生存期已擴展到引用n的范圍
如果這些替代方案確實是給定的,則不清楚為什么您根本需要引用/指針。 您也可以按值返回:
Node computeNode() {
// Do some computation before creating a node object.
Node newNode;
newNode.member1 = xyz;
newNode.member2 = abc;
return newNode;
}
盡管有許多人認為,但這實際上並不是很低效,因為編譯器可以(並且將!)淘汰大多數不必要的副本 。
從語義上講,這是您想要的解決方案,除非節點也存儲在其他位置,並且您需要保留引用身份。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.