14

我刚刚了解了名为“placement new”的 C++ 构造。它允许您精确控制指针在内存中指向的位置。它看起来像这样:

 #include <new>        // Must #include this to use "placement new"
 #include "Fred.h"     // Declaration of class Fred

 void someCode()
 {
   char memory[sizeof(Fred)];
   void* place = memory;

   Fred* f = new(place) Fred();   // Create a pointer to a Fred(),
                                  // stored at "place"

   // The pointers f and place will be equal

   ...
 } 

(来自C++ FAQ Lite的示例)

在此示例中,thisFred 的指针将等于place


我已经看到它在我们团队的代码中使用过一两次。根据您的经验,这种结构能带来什么?其他指针语言有类似的结构吗?对我来说,这似乎让人想起equivalenceFORTRAN,它允许不同的变量占据内存中的相同位置。

4

12 回答 12

15

它允许您进行自己的内存管理。通常,这最多只会让您的性能略有提高,但有时这是一个巨大的胜利。例如,如果您的程序使用大量标准大小的对象,您可能希望创建一个分配一个大内存的池。

这类事情也在 C 中完成,但由于 C 中没有构造函数,因此不需要任何语言支持。

于 2008-12-12T15:03:34.283 回答
12

它还用于嵌入式编程,其中 IO 设备通常映射到特定的内存地址

于 2008-12-12T15:02:16.970 回答
8

它在构建自己的容器(如对象)时很有用。

例如,如果您要创建一个矢量。如果您为大量对象保留空间,您希望使用某种不调用对象构造函数的方法(如 new char[sizeof(object) * reserveSize])分配内存。然后,当人们开始将对象添加到向量中时,您可以使用placement new 将它们复制到分配的内存中。

template<typename T>
class SillyVectorExample
{
    public:
        SillyVectorExample()
            :reserved(10)
            ,size(0)
            ,data(new char[sizeof(T) * reserved])
        {}
        void push_back(T const& object)
        {
            if (size >= reserved)
            {
                // Do Somthing.
            }
            // Place a copy of the object into the data store.
            new (data+(sizeof(T)*size))  T(object);
            ++size;
        }
        // Add other methods to make sure data is copied and dealllocated correctly.
    private:
        size_t   reserved;
        size_t   size;
        char*    data;
 };

PS。我不提倡这样做。这只是容器如何工作的一个简化示例。

于 2008-12-12T18:28:33.387 回答
7

我在共享内存段中构造对象时使用过它。

于 2008-12-12T15:13:02.080 回答
5

放置 new 可用于创建类型安全的联合,例如 Boost 的variant.

union 类包含一个与其指定包含的最大类型一样大的缓冲区(并且具有足够的对齐方式)。它new根据需要将对象放置到缓冲区中。

于 2008-12-12T14:55:37.327 回答
4

我在内核模式下做 C++ 时使用这个结构。

我使用内核模式内存分配器并在分配的块上构造对象。

所有这些都包含在类和函数中,但最后我做了一个新的放置。

于 2008-12-12T14:51:46.740 回答
4

放置 new 不是为了让指针相等(你可以使用赋值!)。

Placement new 用于在特定位置构造对象。在 C++ 中有三种构造对象的方法,而放置 new 是唯一一种可以让您显式控制该对象“存在”的位置的方法。这对一些事情很有用,包括共享内存、低级设备 I/O 和内存池/分配器实现。

通过堆栈分配,对象在堆栈顶部构造,无论当前碰巧在哪里。

使用“常规”new,对象在堆上的一个有效的任意地址构造,由标准库管理(除非您覆盖了 operator new)。

放置 new 说“专门在这个地址为我构建一个对象”,它的实现只是 operator new 的重载,它返回传递给它的指针,作为获取 new 运算符的其余机制的一种手段,它构造运算符 new 函数返回的内存中的对象。

还值得注意的是 operator new 函数可以用任意参数重载(就像任何其他函数一样)。这些其他参数通过“new(arg 2, arg3, ..., argN)”语法传递。Arg1 总是隐式传递为“sizeof(无论你在构造什么)”。

于 2008-12-13T04:12:41.710 回答
2

通过控制确切的位置,您可以对齐内存中的内容,这有时可用于提高 CPU 获取/缓存性能。虽然从未真正看到它在使用中

于 2008-12-13T06:16:38.293 回答
1

Placement new 允许开发人员从预先分配的内存块中分配内存。如果系统更大,那么开发人员会选择使用placement new。现在我正在开发一个更大的航空电子软件,我们在开始时分配执行应用程序所需的大内存。我们使用placement new 在需要的地方分配内存。它将性能提高到一定程度。

于 2008-12-13T03:54:41.030 回答
1

它在将内存分页到硬盘驱动器上的文件时很有用,在操作大型对象时可能会这样做。

于 2008-12-12T14:55:14.083 回答
0

在我看来,这就像在堆栈上分配对象的一种方式..

于 2008-12-12T15:09:12.430 回答
0

我用它来创建基于包含从网络接收到的消息的内存的对象。

于 2008-12-13T05:18:02.467 回答