什么是C ++构造“放置新”的用途?

时间:2008-12-12 14:47:02

标签: c++ memory new-operator placement-new equivalence

我刚刚了解了名为“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的例子)

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


我已经看到它在我们团队的代码中使用过一次或两次。根据您的经验,这个构造能够实现什么?其他指针语言是否有类似的结构?对我来说,它似乎让人联想到FORTRAN中的equivalence,它允许不同的变量占据内存中的相同位置。

12 个答案:

答案 0 :(得分:15)

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

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

答案 1 :(得分:12)

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

答案 2 :(得分:7)

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

答案 3 :(得分:7)

在构建像对象一样的容器时很有用。

例如,如果您要创建矢量。如果为大量对象保留空间,则需要使用一些不调用对象构造函数的方法来分配内存(如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。我不是在鼓吹这样做。这只是容器如何工作的简化示例。

答案 4 :(得分:5)

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

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

答案 5 :(得分:4)

Placement new不是关于使指针相等(你可以只使用赋值!)。

Placement new用于在特定位置构建对象。在C ++中有三种构造对象的方法,而placement new是唯一一种可以让你明确控制对象“存在”的方法。这对于多种内容非常有用,包括共享内存,低级设备I / O和内存池/分配器实现。

使用堆栈分配,对象构建在堆栈的顶部,无论当前发生的是什么。

使用“regular”new,对象在堆上的有效任意地址构造,由标准库管理(除非你重写了operator new)。

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

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

答案 6 :(得分:4)

在内核模式下执行C ++时使用此构造。

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

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

答案 7 :(得分:2)

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

答案 8 :(得分:1)

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

答案 9 :(得分:1)

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

答案 10 :(得分:0)

在我看来,

就像在堆栈中分配对象一样..

答案 11 :(得分:0)

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

豫ICP备18024241号-1