"placement new“运算符声明如下:
void* operator new (std::size_t size, void* ptr) noexcept;
但是,虽然它不涉及任何实际分配,因此消除了不好的分配异常,但仍然有可能指针指向一个不好的位置,在这种情况下,人们可能会得到一个范围或上/下溢出错误,但它被声明为noexcept
的事实不会直接终止执行吗?
这是否意味着在放置C++11之前,new将抛出并尝试在std::set_unexpected
情况下处理std::unexpected
,而不是直接崩溃?
难道不应该有一个重载的位置新的“以防万一”?
发布于 2014-11-02 20:58:46
使用放置语法的要点是实现非标准分配,因此通常需要非标准释放。因此,所采取的操作取决于所使用的分配器。
你的工作就是为新员工提供正确的工作地址。
为回应评论而编辑:
#include <new> // Must #include this to use "placement new"
#include "Fred.h" // Declaration of class Fred
void someCode()
{
char memory[sizeof(Fred)]; // Line #1 //Allocate enough memory.
void* place = memory; // Line #2 // There's no need for this.
Fred* f = new(place) Fred(); // Line #3 (see "NOTE" below)
// The pointers f and place will be equal
...
}
注意:传递给"placement new“操作符的指针指向足够大的内存区域,并且与您创建的对象类型对齐,这是您唯一的责任。无论是编译器还是运行时系统都不会尝试检查您这样做是否正确。如果您的Fred类需要在4字节的边界上对齐,但您提供的位置没有正确对齐,那么您可能会遇到严重的灾难。
简而言之,这意味着你应该小心使用placement new,或者如果你是像我这样的人,那么永远不要使用它:)
希望这能消除你的疑虑。
发布于 2014-11-02 21:42:12
要理解这个函数的作用,我认为有必要看一看new-expression的作用:它调用一个分配函数来获取对象的存储空间,然后在分配函数指定的内存区域中构造该对象(通过返回指向所述内存区域的指针)。
这意味着构造永远不会由分配函数本身执行。分配函数有一个奇怪的名字operator new
。
可以通过使用placement-new语法为分配函数提供其他参数:
new int(5) // non-placement form
new(1,2,3) int(5) // placement-form
但是,placement new通常引用一个非常具体的new-expression
void* address = ...;
::new(address) int(5) // "the" placement-form
这种形式的目的是在已经分配的内存区域中构造一个对象,即它只调用构造函数,而不执行任何分配。
在核心语言中还没有为这种情况引入特殊情况。相反,在标准库中添加了一个特殊的分配函数:
void* operator new (std::size_t size, void* ptr) noexcept;
作为一个无操作(return ptr;
),它允许显式地调用对象的构造函数,在给定的内存位置进行构造。编译器可以消除这种函数调用,因此不会引入任何开销。
发布于 2014-11-02 20:49:21
Placement new
的存在使得显式构造函数调用可以指向任意缓冲区(用于自定义分配器、调试等)。事情就是这样。
您可以编写自己的代码来验证其输入。
例如:一个类可能需要某种对齐,而您怀疑某个自定义分配器在编造这一点。所以,你给这个类一个不同的位置,看看当分配器使用它时会发生什么。
https://stackoverflow.com/questions/26699326
复制相似问题