簡體   English   中英

這是 C++ 中的未定義行為嗎?

[英]Is this undefined behavior in C++?

此示例是從cppreference復制的。

struct Y { int z; };
alignas(Y) std::byte s[sizeof(Y)];
Y* q = new(&s) Y{2};
const int f = reinterpret_cast<Y*>(&s)->z; // Class member access is undefined
                                           // behavior: reinterpret_cast<Y*>(&s)
                                           // has value "pointer to s" and does
                                           // not point to a Y object
const int g = q->z; // OK
const int h = std::launder(reinterpret_cast<Y*>(&s))->z; // OK

我想知道在上面的語句之后添加像s[0] = std::byte{0}這樣的操作是否是未定義的行為? 它似乎並沒有違反嚴格的別名規則,因為根據cppreferencestd::byte可以是任何類型的“AliasedType”,這意味着將任何 object 視為字節數組是合法的。

請注意,我添加了 c++20 label,因為它們可能僅在 C++20 之后才被明確定義。

感謝@LanguageLawyer 的更正,我已經更新了我的答案。


我想知道在上面的語句之后添加像 s[0] = std::byte{0} 這樣的操作是否是未定義的行為?

我相信這是一種未定義的行為,但原因與嚴格的別名規則無關。 嚴格的別名規則 state 如果程序通過T類型的左值訪問D類型的 object 但DT不是“相似的”並且T不是那些特殊字符類型之一,則程序具有未定義的行為。 在您的情況下,您正在通過 std::byte 類型的 glvalue 訪問std::byte std::byte ,這在嚴格的別名規則下完全沒問題。

這里真正的問題是, s還為另一個Y object提供了存儲。在放置new表達式之前, s為數組元素提供了存儲。 一旦在s提供的存儲中構造了Y object,數組元素的生命周期就會終止:

[基本生活]/1.2:

類型 T 的 object o 的生命周期在以下情況結束:

  • 如果 T 是非類類型,則 object 被銷毀,或者
  • 如果 T 是 class 類型,析構函數調用開始,或者
  • object 占用的存儲被釋放,或者被未嵌套在 o ([intro.object]) 中的 object 重用。

因此,如果您在 new 表達式之后訪問s[0] ,則您訪問的是生命周期外的 object,這是一種未定義的行為。

它似乎並沒有違反嚴格的別名規則,因為 std::byte 可以是任何類型的“AliasedType”

雖然std::byte可以是任何東西的AliasedType ,但它不在這個片段中。 YAliasedType ,因為我們正在嘗試通過Y 2類型的左值訪問 object 1

將任何 object 視為字節數組是合法的

將任何 object 視為字節數組確實是合法的。 然而,這個reinterpret_cast試圖做完全相反的事情:將字節數組視為其他類型。 這不是,也從來不是合法的。

--
1在這種情況下, s
2在這種情況下, *reinterpret_cast<Y*>(&s)

暫無
暫無

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

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