[英]Return by reference in C++ - Reference assignment vs value assignment
假設我有:
class SomeObject {
};
SomeObject& f() {
SomeObject *s = new SomeObject();
return *s;
}
// Variant 1
int main() {
SomeObject& s = f();
// Do something with s
}
// Variant 2
int main() {
SomeObject s = f();
// Do something with s
}
第一個變體和第二個變體之間有什么區別嗎? 在任何情況下,我都會使用一個?
編輯:另一個問題,在兩種情況下s
包含什么?
首先,您永遠都不想返回對在函數中動態分配的對象的引用。 這是等待發生的內存泄漏。
除此之外,它還取決於對象的語義以及您在做什么。 使用引用(變量1)可以修改其引用的對象,以便其他功能可以看到修改后的值。 聲明一個值(變量2)意味着您擁有自己的本地副本,並且將對其進行任何修改等,而不是對函數返回中引用的對象進行任何修改。
通常,如果函數返回對非const的引用,那是因為它希望修改該值。 一個典型的例子是類似std::vector<>::operator[]
的表達式,其中的表達式是:
v[i] = 42;
預期會修改向量中的元素。 如果不是這種情況,則該函數應返回一個值,而不是引用(並且您幾乎永遠不應使用此類函數來初始化本地引用)。 當然,只有返回對其他位置可訪問內容的引用,這才有意義。 函數所屬的類所擁有的全局變量或(更可能是)數據。
在第一個變體中,您將引用直接附加到動態分配的對象。 這是擁有動態內存的一種非常不合常規的方法(指針將更適合於該目的),但是它仍然為您提供了適當地重新分配該對象的機會。 即在您的第一個main
結束時,您可以執行
delete &s;
在第二個變體中,您將丟失引用,即,您將丟失指向該動態分配對象的唯一鏈接。 該對象成為內存泄漏。
同樣,通過引用擁有動態分配的對象並不是一個好習慣。 為此通常最好使用指針或智能指針。 因此,即使第一個變體可以正式兌換,您的兩個變體也存在缺陷。
變體1將復制對象的地址,並且速度很快
變體2將復制整個對象,並且速度很慢(如變體2中已指出的那樣,您不能通過調用new來刪除創建的對象)
編輯:兩個f包含相同的Object
您詢問的兩個選項都不是很好。 在這種特殊情況下,應該使用shared_ptr
或unique_ptr
,如果使用的是較舊的C ++編譯器,則應使用auto_ptr
,並更改函數以使其返回指針而不是引用。 另一個好的選擇是按值返回對象,尤其是在對象很小且構造便宜的情況下。
修改以按值返回對象:
SomeObject f() { return SomeObject(); }
SomeObject s(f());
簡單,干凈,安全-這里沒有內存泄漏。
使用unique_ptr
:
SomeObject* f() { return new SomeObject(); }
unique_ptr<SomeObject> s(f());
在此處使用unique_ptr
或shared_ptr
的優點之一是,您可以在某個時候更改函數f
以返回派生自SomeObject
的類的對象,並且無需更改任何客戶端代碼-只需確保基類( SomeObject
)具有虛擬構造函數。
為什么您考慮的選項不是很好:
變體1:
SomeObject& s = f();
您將如何銷毀物體? 無論如何,您都將需要該對象的地址來調用它的析構函數,因此有時需要取消引用s
所指的對象( &s
)。
變體2。您在這里泄漏,沒有機會調用從函數返回的對象的析構函數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.