我的印象是访问union除最后一个成员之外的成员是UB,但我似乎无法找到一个可靠的参考(除了声称它是UB但没有标准支持的答案).
那么,这是不确定的行为?
(参考这个问题和答案.)
在C++ 17标准之前,[basic.compound]/3中包含以下句子:
如果类型T的对象位于地址A,则类型为cv T*的指针(其值为地址A)被称为指向该对象,而不管该值是如何获得的.
但是自从C++ 17以来,这句话已被删除.
例如,我相信这句话使这个示例代码定义,并且从C++ 17开始这是未定义的行为:
alignas(int) unsigned char buffer[2*sizeof(int)];
auto p1=new(buffer) int{};
auto p2=new(p1+1) int{};
*(p1+1)=10;
Run Code Online (Sandbox Code Playgroud)
在C++ 17之前,p1+1保持地址*p2并具有正确的类型,因此*(p1+1)是指向*p2.在C++中,17 p1+1是一个指向前端的指针,所以它不是指向对象的指针,我相信它不是可以解除引用的.
对标准权的这种修改的解释是否还有其他规则来补偿所引用的句子的删除?
请考虑以下包含一些环境值的结构:
struct environment_values {
uint16_t humidity;
uint16_t temperature;
uint16_t charging;
};
Run Code Online (Sandbox Code Playgroud)
我想为这些带有幻像类型*的值添加一些额外的信息,并同时使它们的类型不同:
template <typename T, typename P>
struct Tagged {
T value;
};
// Actual implementation will contain some more features
struct Celsius{};
struct Power{};
struct Percent{};
struct Environment {
Tagged<uint16_t,Percent> humidity;
Tagged<uint16_t,Celsius> temperature;
Tagged<uint16_t,Power> charging;
};
Run Code Online (Sandbox Code Playgroud)
内存布局是Environment一样的environment_values吗?这是否也适用于混合类型布局,例如:
struct foo {
uint16_t value1;
uint8_t value2;
uint64_t value3;
}
struct Foo {
Tagged<uint16_t, Foo> Value1;
Tagged<uint8_t , Bar> Value2;
Tagged<uint64_t, Quux> Value3;
}
Run Code Online (Sandbox Code Playgroud)
对于我迄今为止尝试过的所有类型,以下断言都是:
template <typename T, …Run Code Online (Sandbox Code Playgroud) 在union U下面,如果a或者b是活动成员,是否定义了要访问的行为c?
struct A{
int a;
};
struct B{
int a;
double b;
};
union U{
A a;
B b;
int c;
};
Run Code Online (Sandbox Code Playgroud)
在[class.union]中,标准定义了一些使用union更简单(强调我的)的规则:
[注意:为了简化联合的使用,我们做了一个特别的保证:如果标准布局联合包含多个共享一个公共初始序列的标准布局结构,并且该标准的对象是非静态数据成员-layout union类型是活动的并且是标准布局结构之一,允许检查任何标准布局结构成员的公共初始序列; 见[class.mem]. - 结束说明]
我在这里挂了单词struct.int即使它不是结构,标准布局标量是否会计数?
我的union U上面确实是[class]之后的"标准布局"联合,它基本上说它需要是一个使用union关键字的标准布局类,而且因为我们只使用标量(标准布局类型),所以它会通过.
结构显然共享一个由第一个成员组成的共同初始序列int,但不清楚基本类型是否可以考虑用于常见的初始序列.
int标准布局中的元素结构,而非int c联合中的static …