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(反面示例)
union Pun {
int x;
unsigned char c[sizeof(int)];
};
The idea of Pun is to be able to look at the character representation of an int.
Pun的想法是可以观察整数的字节表现。
void bad(Pun& u)
{
u.x = 'x';
cout << u.c[0] << '\n'; // undefined behavior
}
If you wanted to see the bytes of an int, use a (named) cast:
如果你希望看到整数的各个字节,使用(命名)转换:
void if_you_must_pun(int& x)
{
auto p = reinterpret_cast(&x);
cout << p[0] << '\n'; // OK; better
// ...
}
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
觉得本文有帮助?请分享给更多人。
关注【面向对象思考】轻松学习每一天!
面向对象开发,面向对象思考!