这里有人用过c++的“placement new”吗?如果有,为什么?在我看来,它只在内存映射硬件上有用。
当前回答
我使用它来创建基于内存的对象,其中包含从网络接收到的消息。
其他回答
如果你想把分配和初始化分开,这是很有用的。STL使用放置new来创建容器元素。
我用它来存储带有内存映射文件的对象。 具体的例子是一个图像数据库,它处理大量的大图像(超过内存容量)。
在http://xll.codeplex.com上查看xll项目中的fp.h文件,它解决了喜欢随身携带维度的数组“与编译器的不必要的亲密关系”问题。
typedef struct _FP
{
unsigned short int rows;
unsigned short int columns;
double array[1]; /* Actually, array[rows][columns] */
} FP;
在序列化时(比如使用boost::serialization),放置new也非常有用。在c++的10年里,这只是我第二次需要新职位的情况(如果你包括面试的话,这是第三次:))。
实际上,实现任何类型的数据结构都需要分配比插入元素数量的最低要求更多的内存(即,除了每次分配一个节点的链接结构之外的任何数据结构)。
以unordered_map、vector或deque等容器为例。这些都为您插入的元素分配了比最低要求更多的内存,以避免为每次插入都需要堆分配。让我们用向量作为最简单的例子。
当你这样做时:
vector<Foo> vec;
// Allocate memory for a thousand Foos:
vec.reserve(1000);
... 其实也造不出一千个foo。它只是为它们分配/保留内存。如果vector没有在这里使用放置new,它将在所有地方默认构造foo,并且必须调用它们的析构函数,即使是对于你从未在第一个位置插入的元素。
分配=建设,解放=毁灭
一般来说,要实现像上面这样的许多数据结构,不能将分配内存和构造元素视为一个不可分割的事情,同样也不能将释放内存和销毁元素视为一个不可分割的事情。
为了避免不必要地向左或向右调用多余的构造函数和析构函数,这就是标准库将std::allocator(在分配/释放内存*时不构造或销毁元素)的思想与使用它的容器分开的原因,这些容器使用放置new手动构造元素,使用显式调用析构函数手动销毁元素。
我讨厌std::allocator的设计,但这是一个不同的主题,我将避免咆哮。: - d
So anyway, I tend to use it a lot since I've written a number of general-purpose standard-compliant C++ containers that could not be built in terms of the existing ones. Included among them is a small vector implementation I built a couple decades ago to avoid heap allocations in common cases, and a memory-efficient trie (doesn't allocate one node at a time). In both cases I couldn't really implement them using the existing containers, and so I had to use placement new to avoid superfluously invoking constructors and destructors on things unnecessary left and right.
当然,如果你曾经使用自定义分配器来单独分配对象,比如一个free list,那么你通常也会想使用placement new,就像这样(基本的例子,不需要担心异常安全或RAII):
Foo* foo = new(free_list.allocate()) Foo(...);
...
foo->~Foo();
free_list.free(foo);