chb*_*er0 10 c++ strict-aliasing language-lawyer
我知道标准中明确允许以下内容:
int n = 0;
char *ptr = (char *) &n;
cout << *ptr;
Run Code Online (Sandbox Code Playgroud)
那这个呢?
alignas(int) char storage[sizeof(int)];
int *ptr = (int *) &storage[0];
*ptr = 0;
cout << *ptr;
Run Code Online (Sandbox Code Playgroud)
本质上,我问的是,别名规则是否允许通过指向另一种类型的指针访问一系列字符.我想参考标准的部分,如果可能的话,表明这种或那种方式.
标准的某些部分让我感到矛盾; (3.10.10)似乎表明在假设动态类型storage
不是的情况下它将是未定义的行为int
.然而,动态类型的定义对我来说并不清楚,而且存在std::aligned_storage
会让我相信这是可能的.
代码int *ptr = (int *) &storage[0]; *ptr = 0;
通过违反严格别名规则导致未定义的行为(C++ 14 [basic.lval]/10)
被访问的对象具有类型,char
但用于访问的glvalue具有类型int
.
a的"动态类型的对象" char
仍然是char
.(动态类型仅与派生类的静态类型不同).C++也没有任何等效的C"有效类型",它允许通过将赋值运算符用于malloc'd空间来"创建"类型化对象.
关于正确使用std::aligned_storage
,你应该使用placement-new在存储中创建一个对象.使用placement-new被认为是结束char
(或任何)对象的生命周期,并创建指定类型的新对象(动态存储持续时间),重新使用相同的存储.然后就没有严格的别名违规.
您可以使用char数组执行相同的操作,例如:
alignas(int) char storage[sizeof(int)];
int *ptr = new(storage) int;
*ptr = 0;
cout << *ptr;
Run Code Online (Sandbox Code Playgroud)
请注意,没有伪析构函数调用或delete
内置类型是必需的int
.如果使用具有非平凡初始化的类类型,则需要这样做.链接到进一步阅读