C++核心準則C.183: 不要使用聯合體實現雙關類型

C++核心準則C.183: 不要使用聯合體實現雙關類型

C.183: Don't use a union for type punning

C.183: 不要使用聯合體實現雙關類型


Reason(原因)

It is undefined behavior to read a union member with a different type from the one with which it was written. Such punning is invisible, or at least harder to spot than using a named cast. Type punning using a union is a source of errors.

向聯合體的一個類型的成員寫入,然後從聯合體不同類型的另一個成員讀出數據的行為是沒有定義的。這樣的雙關性操作無法發現,或者至少比使用命名轉換更難發現。使用聯合體實現雙關類型是錯誤的源頭。

Example, bad(反面示例)

<code>union Pun {
int x;
unsigned char c[sizeof(int)];
};/<code>

The idea of Pun is to be able to look at the character representation of an int.

Pun的想法是可以觀察整數的字節表現。

<code>void bad(Pun& u)
{
u.x = 'x';
cout << u.c[0] << '\\n'; // undefined behavior
}/<code>

If you wanted to see the bytes of an int, use a (named) cast:

如果你希望看到整數的各個字節,使用(命名)轉換:

<code>void if_you_must_pun(int& x)
{
auto p = reinterpret_cast<unsigned>(&x);
cout << p[0] << '\\n'; // OK; better
// ...
}/<unsigned>/<code>

Accessing the result of an reinterpret_cast to a different type from the objects declared type is defined behavior (even though reinterpret_cast is discouraged), but at least we can see that something tricky is going on.

使用reinterpret_case將一個對象從它被定義的類轉換為不同的類型之後訪問其結果是被定義的行為(即使是這樣也不推薦使用reinterpret_cast),但是至少我們可以看到某些危險的處理正在進行。


Note(注意)

Unfortunately, unions are commonly used for type punning. We don't consider "sometimes, it works as expected" a strong argument.

C++17 introduced a distinct type std::byte to facilitate operations on raw object representation. Use that type instead of unsigned char or char for these operations.

不幸的是,聯合體經常被用於雙關類型。我們不認為“有時會按照預期動作”是一個很有力的觀點。C++17引入了新類型std::byte以協助表現針對原始對象的操作。在這些操作中應該使用std::byte而不是unsigned char。

Enforcement(注意)

???

原文鏈接:

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c183-dont-use-a-union-for-type-punning


覺得本文有幫助?請分享給更多人。

面向對象開發,面向對象思考!​


分享到:


相關文章: