簡體   English   中英

C ++:按引用返回按值返回

[英]C++: Return by reference to return by value

我一直在閱讀邁爾斯的書,並通過引用/指針和值返回來查看項目。 關鍵是,如果我們的函數是這樣的:

ClassA& AddSomething(ClassA classA)
{
  ClassA tempClassA;
  //... do something on tempClassA
  return tempClassA;
}

這不起作用,因為我們返回對堆棧上創建的對象的引用,並且現在函數已經完成。

他給出了兩個解決方案

  1. 在函數內部使用本地靜態ClassA。 這有它的問題,但至少我們可以確定該對象存在。
  2. 作為對象返回:

     ClassA AddSomething(ClassA classA) { ClassA tempClassA; //... do something on tempClassA return tempClassA; } 

現在,如果我要這樣做:

ClassA obj1;
ClassA obj2 = AddSomething(obj1);

我現在的困惑是,在執行此行時:

  1. 創建一個tempClassA的'副本'並傳遞給ClassA的復制構造函數(初始化obj2)? 要么
  2. tempClassA將自身傳遞給ClassA的復制構造函數,因為復制構造函數接受引用。

所以基本上,傳遞給復制構造函數的是對tempClassA的引用(在函數內部的堆棧中創建)或對tempClassA副本的引用。

另外,我的另一個問題是,我已經讀過,如果我得到函數局部變量的引用,那么本地變量將不會被刪除。 例如,

ClassA & classRef = AddSomething(obj1);

在這種情況下,如果AddSomething()返回引用,則classRef不指向已刪除的引用,因為將保留本地變量。 我理解正確嗎?

在最壞的情況下,你是對的: tempClassA的副本被傳遞給復制構造函數。 但是允許編譯器消除該副本並從tempClassA構造結果。 這稱為“返回值優化”或RVO。 我不知道沒有這樣做的編譯器。

當按值返回對象時,會發生兩個副本:一個從局部變量返回到返回值,另一個從返回值返回到目標對象。 然而,實現允許一個的Elid或兩個副本; 這在第一種情況下稱為返回值優化 (RVO),在第二種情況下稱為復制省略

Object some_function() {
    return Object();    // copy Object() into return value; candidate for RVO
}
Object another_function() {
    Object obj;
    return obj;         // copy obj into return value; candidate for NRVO
}
Object result = some_function();   // copy return value into result; candidate for copy elision

上面的第二個函數是RVO的細化類型的候選函數,稱為命名返回值優化; 最簡單的RVO形式僅適用於構造返回值的返回語句。

關於第二個問題,生命周期擴展僅適用於對value返回的對象的const引用; 第二個問題中的代碼不會延長任何對象的生命周期。 有關更多詳細信息,請參閱返回臨時對象和綁定到const引用

您永遠不能通過引用返回函數局部變量。 即使您使用const引用捕獲返回的值,它也不會工作,如下所示:

const ClassA& classRef = AddSomething(obj1);

因為如果AddSomething通過引用返回本地對象,那么在classRef引用它時,它將是對不存在的對象的懸空引用。

暫無
暫無

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

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