通过new char[sizeof(T)]保证分配一个缓冲区来分配一个缓冲区,该内存是为该类型正确对齐的T,其中所有成员T都有其自然的,实现定义的对齐方式(也就是说,您没有使用该alignas关键字来修改它们的对齐方式).
我已经看到这个保证在这里得到了一些答案,但我并不完全清楚标准是如何达到这个保证的.5.3.4-10标准给出了基本要求:基本上new char[]必须与之对齐max_align_t.
我所缺少的是所说的位alignof(T)总是有效的对齐,最大值为max_align_t.我的意思是,这似乎是显而易见的,但结构的最终对齐必须至多max_align_t吗?即使点3.11-3表示可能支持扩展对齐,编译器可能自己决定一个类是一个过度对齐的类型?
当我使用g ++编译这个示例代码时,我收到此警告:
警告:解除引用类型惩罚指针将破坏严格别名规则
[-Wstrict-aliasing]
代码:
#include <iostream>
int main()
{
alignas(int) char data[sizeof(int)];
int *myInt = new (data) int;
*myInt = 34;
std::cout << *reinterpret_cast<int*>(data);
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,不是data别名int,因此将其强制转换为int不会违反严格的别名规则?或者我在这里遗漏了什么?
编辑:奇怪,当我这样定义时data:
alignas(int) char* data = new char[sizeof(int)];
Run Code Online (Sandbox Code Playgroud)
编译器警告消失了.堆栈分配是否与严格别名产生差异?事实上它是一个char[]而不是一个char*意味着它实际上不能为任何类型别名吗?
我最近看到像这样的类用于"按需"构造对象,而不必出于各种原因使用动态内存分配.
#include <cassert>
template<typename T>
class StaticObject
{
public:
StaticObject() : constructed_(false)
{
}
~StaticObject()
{
if (constructed_)
((T*)object_)->~T();
}
void construct()
{
assert(!constructed_);
new ((T*)object_) T;
constructed_ = true;
}
T& operator*()
{
assert(constructed_);
return *((T*)object_);
}
const T& operator*() const
{
assert(constructed_);
return *((T*)object_);
}
private:
bool constructed_;
alignas(alignof(T)) char object_[sizeof(T)];
};
Run Code Online (Sandbox Code Playgroud)
这段代码,即将正确对齐的char数组转换为对象指针,被C++ 14标准视为未定义的行为,还是完全没问题?