C++ 构造“placement new”的用途是啥?

Posted

技术标签:

【中文标题】C++ 构造“placement new”的用途是啥?【英文标题】:What are uses of the C++ construct "placement new"?C++ 构造“placement new”的用途是什么? 【发布时间】:2010-09-26 15:37:48 【问题描述】:

我刚刚了解了名为“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,它允许不同的变量在内存中占据相同的位置。

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

您所描述的问题应该通过使用适当的内存分配器来解决,重载placement new 可能不是最好的做法。 正确 -- 使用模板库时。否则,会有新的展示位置。 当然,C++ 中有很多地方现在有更好的方法来做到这一点。例如,我已经很多年没有写过 delete [] 了。但是,周围有很多旧代码确实使用了新位置等。【参考方案2】:

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

【讨论】:

【参考方案3】:

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

例如,如果您要创建一个矢量。如果您为大量对象保留空间,您希望使用某种不调用对象构造函数的方法(如 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;
 ;

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

【讨论】:

你有什么更具体的例子说明你什么时候会真正使用它吗? 更具体的意思是什么?容器就是一个很好的例子。我确信需要保留空间的 STL 容器将以某种形式使用新的放置(可能通过分配器,但我没有看过,所以这只是一个假设)。【参考方案4】:

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

【讨论】:

【参考方案5】:

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

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

【讨论】:

【参考方案6】:

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

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

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

【讨论】:

【参考方案7】:

Placement new 不是让指针相等(你可以使用赋值来实现它!)。

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

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

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

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

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

【讨论】:

【参考方案8】:

通过控制确切的位置,您可以对齐内存中的内容,这有时可用于提高 CPU 获取/缓存性能。 不过,实际上从未见过它在使用中

【讨论】:

我实际上只是遇到了对它的确切需求。在嵌入式编程中,您通常没有动态分配。因此将对象放置在内存位置并自动调用构造函数很方便。这正是它的作用【参考方案9】:

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

【讨论】:

你能详细说明一下吗?对分页有用吗?还是对回页有用?我看到分页返回,并没有完全想象分页。【参考方案10】:

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

【讨论】:

【参考方案11】:

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

【讨论】:

好吧,这就是 vanilla new 所做的,但通常你无法指定堆栈的位置。 Tommy:你在想堆 好吧,在上面最初发布的问题中,它实际上最终在堆栈上更新,因为创建的数组缓冲区在堆栈上。但事实并非如此。也许一个更好的例子是使用堆分配内存和 malloc()...【参考方案12】:

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

【讨论】:

以上是关于C++ 构造“placement new”的用途是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Placement new的用法及用途

C++中的newoperator new与placement new

C++内存管理(new operator/operator new/operator delete/placement new)

C++内存分配方法new与placement new使用方法详解

将placement new 与存储类一起使用时的额外构造

Item 52:写了placement new就要写placement delete