我仍在努力理解严格别名规则中允许和不允许的内容。通过这个具体示例,是否违反了严格别名规则?如果没有,为什么?是因为我将不同类型的placement new放置到char *缓冲区中吗?
template <typename T>
struct Foo
{
struct ControlBlock { unsigned long long numReferences; };
Foo()
{
char* buffer = new char[sizeof(T) + sizeof(ControlBlock)];
// Construct control block
new (buffer) ControlBlock{};
// Construct the T after the control block
this->ptr = buffer + sizeof(ControlBlock);
new (this->ptr) T{};
}
char* ptr;
T* get() {
// Here I cast the char* to T*.
// Is this OK because T* can alias char* or because
// I placement newed a T at char*
return (T*)ptr;
}
};
记载一下,void* 可以与任何类型指针别名,而且任何类型指针也可以与 void* 别名。一个 char* 可以与任何类型指针别名,但反过来是否成立呢?如果对齐正确,任何类型都可以别名为 char* 吗?所以下面这种写法是允许的吗?
char* buffer = (char*)malloc(16);
float* pFloat = buffer;
*pFloat = 6; // Can any type pointer alias a char pointer?
// If the above is illegal, then how about:
new (pFloat) float; // Placement new construct a float at pointer
*pFloat = 7; // What about now?
一旦我将char*缓冲区指针分配给新分配的内存,为了将其用作float缓冲区,我是否需要循环并在每个位置上使用placement new创建一个float?如果一开始没有将分配分配给char*,而是直接将其分配给float*,那么我就能立即将其用作float缓冲区,对吗?
std::launder
。有一些复杂的规则,可能会导致ptr
指向一个“旧”的地址。请参考@eerorika的答案,并接受它,因为我认为在这方面它更好。 - Quimbyp1
和p2
。 此外,正如 eerorika 所说,p2
应该从放置 new 中重新分配,例如p2= new (p2) MyStruct2()
。你可以有许多指向同一地址的不同指针,比如int* p1=0;float* p2=0; T* p3=0;
,这肯定不会违反任何规则,对吧? - Quimby