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
。
联合类包含一个与其指定包含的最大类型一样大的缓冲区(并且具有足够的对齐)。它根据需要将new
s 对象放入缓冲区。
【讨论】:
【参考方案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”的用途是啥?的主要内容,如果未能解决你的问题,请参考以下文章
C++中的newoperator new与placement new
C++内存管理(new operator/operator new/operator delete/placement new)