簡體   English   中英

在C ++中按引用返回-引用分配與值分配

[英]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_ptrunique_ptr ,如果使用的是較舊的C ++編譯器,則應使用auto_ptr ,並更改函數以使其返回指針而不是引用。 另一個好的選擇是按值返回對象,尤其是在對象很小且構造便宜的情況下。

修改以按值返回對象:

SomeObject f() { return SomeObject(); }

SomeObject s(f());

簡單,干凈,安全-這里沒有內存泄漏。

使用unique_ptr

SomeObject* f() { return new SomeObject(); }

unique_ptr<SomeObject> s(f());

在此處使用unique_ptrshared_ptr的優點之一是,您可以在某個時候更改函數f以返回派生自SomeObject的類的對象,並且無需更改任何客戶端代碼-只需確保基類( SomeObject )具有虛擬構造函數。

為什么您考慮的選項不是很好:

變體1:

SomeObject& s = f();

您將如何銷毀物體? 無論如何,您都將需要該對象的地址來調用它的析構函數,因此有時需要取消引用s所指的對象( &s )。

變體2。您在這里泄漏,沒有機會調用從函數返回的對象的析構函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM