这是新的展示位置。
虽然您通常不会将它与整数类型一起使用。
它通常用于构建缓冲区,然后在其中构建其他类型。
// Allocate a buffer with enough room for two T objects.
char* buffer = new char[sizeof(T) * 2];
// Allocate a T in slot zero
T* t1 = new (buffer + 0 * sizeof(T)) T("Zero");
// Allocate a T in slot one
T* t2 = new (buffer + 1 * sizeof(T)) T("One");
这就是基础。
但请记住,用placement new 分配的对象不能用delete 语句删除。这是因为delete 试图回收new 分配的内存(以及调用析构函数)。所以要正确使用这些对象,你必须手动调用那里的析构函数。
t1->~T();
t2->~T();
不要忘记删除原始缓冲区。
delete [] buffer;
其他一些注意事项:
人们经常看到缓冲区可以在堆栈上实现,从而自动释放
char buffer[sizeof(T) * 2];
不幸的是,这在技术上可能没问题(它可以编译)。但它不能保证可以工作,因为缓冲区的内存可能无法正确对齐以将 T 放置在其中。因此,您必须动态分配缓冲区(通过使用 new 它保证内存针对分配的任何大小的对象正确对齐(因此通过扩展,它也针对小于分配大小的任何大小对齐)。绕过的简单方法这个问题是使用 std::vector
std::vector<char> buffer(sizeof(T) * 2);
T* t1 = new (&buffer[0] + 0 * sizeof(T)) T("Zero");
T* t2 = new (&buffer[0] + 1 * sizeof(T)) T("One");
placement new 的另一个用途是重置对象。
我已经看到这样做了,但我更喜欢使用更标准的赋值运算符:
T obj1("Plop");
obj1 = T("Another Plop");
// Can be done like this:
T obj1("Plop");
obj1.~T();
new (&obj1) T("Another Plop"); // Seems excessive to me. But can be us-full
// in some extreme situations.
请记住,如果您使用重置方法,您必须先销毁旧对象(否则该对象可能无法正常运行)。