[英]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子句參數除外)的名稱時,通過將自動對象直接構造到函數的返回值中,可以省略復制/移動操作
沒有理由應該導致內存泄漏。 如果類在其構造函數中執行一些動態分配,則將對象直接構造到函數的返回值中時會發生這種情況。
根據您的評論(其中foo1
和foo2
都構造T
對象並返回它們):
T a = foo1();
a = foo2();
我們不僅在這里查看RVO,而且還在嘗試從臨時結構構造對象時發生另一種復制省略。
在第一行中,可以刪除兩個副本/動作:
foo1
返回構造的對象 a
也就是說,在構造的對象foo1
可以直接在的位置創建a
。 如果構造動態分配一些對象,將只進行一次,為a
對象。
在第二行中,可以刪除單個復制/移動-僅從函數返回。 因此,將在函數的返回值中直接創建foo2
構造的對象,然后將其復制/移動分配 a
。 不會忽略復制/移動任務。
然后,由復制/移動分配運算符來確保原始分配的資源被安全地丟棄,並且唯一剩余的資源是在foo2
內部創建的資源。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.