IsoCpp.org提供有关新展示位置的FAQ:
他们提供的例子是:
#include <new> // Must #include this to use "placement new"
#include "Fred.h" // Declaration of class Fred
void someCode()
{
char memory[sizeof(Fred)]; // Line #1
void* place = memory; // Line #2
Fred* f = new(place) Fred(); // Line #3 (see "DANGER" below)
// The pointers f and place will be equal
// ...
}
上述代码不会违反C ++的严格别名规则,因为place
和memory
是不同的类型,但引用相同的内存位置?
(我知道char
类型的指针可以为任何其他类型添加别名,但是在这里我们似乎有一个void*
别名为char*
,根据我的理解这是不允许的? )
我怀疑大多数内存分配器也会以类似的方式违反严格的别名规则。使用贴图新建时,遵循严格别名规则的正确方法是什么?
谢谢
答案 0 :(得分:5)
没有问题,因为代码没有引用javah
。让指针相等并不会导致UB - 它通过这两个指令是间接的,这是禁止的。
例如,以下是合法的:
*place
请参阅 struct A {int x;} a;
struct B {} *pb = reinterpret_cast<B*>(&a);
A* pa = reinterpret_cast<A*>(pb);
,并且您违反了严格的别名规则。
在您的特定示例中,您无法撰写*pb
因为这会产生*place
类型的左值,这是不允许的。
还要注意Cornstalks的观点:该示例确实需要使用void
,因为无法保证std::aligned_storage
对象memory
正确对齐。在实践中,这通常并不重要,因为您将使用Fred
或new
(确实返回适当对齐的存储空间)为新的展示位置分配内存。
答案 1 :(得分:3)
使用展示位置时遵循严格别名规则的正确方法是什么?
正确的方法是使用std::aligned_storage
。该代码示例并不保证Fred
的正确存储对齐,因此不应使用它。
正确的方法是:
#include <new> // For placement new
#include <type_traits> // For std::aligned_storage
struct Fred {
// ...
};
void someCode() {
std::aligned_storage<sizeof(Fred), alignof(Fred)>::type memory;
// Alternatively, you can remove the "alignof(Fred)" template parameter if you
// are okay with the default alignment, but note that doing so may result in
// greater alignment than necessary and end up wasting a few bytes.
Fred* f = new(&memory) Fred();
}
上述代码是否会违反C ++的严格别名规则,因为地点和内存是不同的类型,但引用相同的内存位置?
现在,关于原始代码中f
,place
和memory
之间的别名问题,请注意,没有任何别名违规。严格别名规则意味着您不能{&#34; dereference a pointer that aliases an incompatible type&#34;。由于您无法取消引用void*
(以及将指针转换为/ void*
的合法性),因此place
没有风险导致严格的别名冲突。