簡體   English   中英

我可以確保RVO用於reintrepret-cast'ed值嗎?

[英]Can I ensure RVO for reintrepret-cast'ed values?

假設我寫了:

Foo get_a_foo() {
    return reinterpret_cast<Foo>(get_a_bar());
}

並假設sizeof(Foo) == sizeof(Bar)

返回值優化是否必然發生在這里,或者當我通過使用reinterpret_cast“違反規則”時,編譯器是否可以做任何他們喜歡的事情? 如果我沒有得到RVO,或者我不能保證它 - 我可以更改此代碼以確保它發生嗎?

我的問題是關於C ++ 11,另外還有C ++ 17(因為如果我沒有弄錯的話,它在RVO中有一些變化)。

假設我寫了:

 Foo get_a_foo() { return reinterpret_cast<Foo>(get_a_bar()); } 

並假設sizeof(Foo) == sizeof(Bar)

對於所有可能的FooBar類型, reinterpret_cast都不合法。 它僅適用於以下情況:

  1. Bar是一個指針, Foo可以是一個指針,也可以是一個足以容納指針的整數/枚舉。
  2. Bar是一個足以容納指針的整數/枚舉,而Foo是一個指針。
  3. Bar是對象類型, Foo是引用類型。

還有一些我沒有涉及的其他案例,但它們要么無關緊要( nullptr_t cast),要么屬於#1或#2的類似問題。

看,elision在處理基本類型時實際上並不重要。 你無法區分如何刪除基本類型的復制/移動而不是忽略它。 那里有轉換嗎? 編譯器只是使用返回值寄存器嗎? 這取決於編譯器,通過“似乎”規則。

返回引用類型時,elision不適用,因此#3已經出局。

但是,如果FooBar是用戶定義的對象類型(或指針,整數或成員指針以外的對象類型),則轉換不正確的 reinterpret_cast不是某種簡單的memcpy轉換函數。

所以,讓我們用一些代碼來代替它,你知道,這些代碼實際上可以工作:

Foo get_a_foo()
{
    return std::bit_cast<Foo>(get_a_bar());
}

其中C ++ 20的std::bit_cast有效地將一個普通的可復制類型轉換為另一個普通的可復制類型。

轉換仍然不會被遺漏。 或者至少,不是通常使用“省略”的方式。

因為這兩種類型都是可復制的,而bit_cast只會調用普通的構造函數,所以編譯器當然可以擦除構造函數,甚至可以使用get_a_foo的返回值對象作為get_a_bar的返回值對象。 因此,它可以被認為是“省略”。

但是“省略”通常指的是標准中允許實現忽略甚至非平凡的構造函數/析構函數的部分。 編譯器只能執行上述操作,因為所有構造函數和析構函數都是微不足道的。 如果它們是非平凡的,那么它們就不會被忽視(那么,如果它們是非平凡的,那么std::bit_cast 將不起作用 )。

我的觀點是,上述轉換的優化不是由於“省略”或RVO規則; 它完全歸功於“似乎”規則。 即使在C ++ 17中, bit_cast調用是否有效地成為noop完全取決於編譯器。 是的,在創建了Foo prvalue之后,C ++ 17需要將它的副本“省略”到函數的返回值對象中。

但轉換本身並不是一個問題。

暫無
暫無

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

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