簡體   English   中英

編譯器如何確定何時可以安全使用RVO?

[英]How does the compiler determine when is it safe to RVO?

編譯器如何確定何時可以安全使用RVO? 不,我不是說右值,而是左值-如果我理解正確,RVO可以通過將目標地址“轉發”給方法來工作,因此它返回目標地址而不是臨時地址,然后復制/分配給目標。

但是編譯器如何知道執行RVO是安全的? 如果左值中已經有一些數據,包括動態分配的資源,該怎么辦? 在這種情況下,RVO可能會導致資源泄漏。 也許有一些規則指定是適用於執行優化還是堅持使用復制或賦值?

RVO只能初始化一個新對象,而不能重新分配現有對象。 因此,在這種情況下:

Thing thing = make_thing();

thing的地址傳遞給函數,函數將其初始化就位。

在這種情況下:

thing = make_thing();

RVO(通常)創建一個臨時對象,然后將其分配給thing 只要可以正確分配類型,就不會有泄漏或類似問題。 由於它是一個臨時的rvalue ,因此可以將其從中移走,這可能比復制更為有效。 如果類型是微不足道的可分配的,則也可以取消該分配-編譯器在選擇如何調用函數時將知道是否是這種情況。

返回值優化是復制省略的一種特殊情況。 如標准所述,它可能在以下情況下發生:

在具有類返回類型的函數的return語句中,當表達式是具有與函數返回類型相同的cv非限定類型的非易失性自動對象(函數或catch子句參數除外)的名稱時,通過將自動對象直接構造到函數的返回值中,可以省略復制/移動操作

沒有理由應該導致內存泄漏。 如果類在其構造函數中執行一些動態分配,則將對象直接構造到函數的返回值中時會發生這種情況。


根據您的評論(其中foo1foo2都構造T對象並返回它們):

T a = foo1();
a = foo2();

我們不僅在這里查看RVO,而且還在嘗試從臨時結構構造對象時發生另一種復制省略。

在第一行中,可以刪除兩個副本/動作:

  1. foo1返回構造的對象
  2. 復制返回的對象為a

也就是說,在構造的對象foo1可以直接在的位置創建a 如果構造動態分配一些對象,將只進行一次,為a對象。

在第二行中,可以刪除單個復制/移動-僅從函數返回。 因此,將在函數的返回值中直接創建foo2構造的對象,然后將其復制/移動分配 a 不會忽略復制/移動任務。

然后,由復制/移動分配運算符來確保原始分配的資源被安全地丟棄,並且唯一剩余的資源是在foo2內部創建的資源。

暫無
暫無

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

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