放置新的和例外

时间:2014-11-02 12:32:33

标签: c++ c++11 exception-handling placement-new nothrow

"放置新"运算符声明为:

void* operator new (std::size_t size, void* ptr) noexcept;

但是虽然它没有涉及任何实际分配,但是消除了错误的分配异常,指针仍然可能指向错误的位置,在这种情况下,人们可能会得到一个范围或上溢/下溢错误,但不是因为它被声明为noexcept只是终止执行而不是这样的事实?

这也意味着在C ++ 11放置之前,如果std::unexpected而不是直接崩溃,则new会抛出并尝试处理std::set_unexpected吗?

不应该放置新的"以防万一"?

4 个答案:

答案 0 :(得分:4)

使用放置语法的目的是实现非标准分配,因此通常需要非标准释放。因此采取的行动取决于所使用的分配器。

您的工作是为新工作地点提供正确的地址。

在回应评论时编辑: -

#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字节边界上对齐,但是您提供的位置未正确对齐,则可能会造成严重的灾难。

简而言之,这意味着如果你这样的人从不使用它,你应该小心使用新的OR:)

希望这会清除你的怀疑。

答案 1 :(得分:2)

要理解这个函数的作用,我认为有必要看一下 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;),它允许显式调用对象的构造函数,在给定的内存位置构造。编译器可以消除此函数调用,因此不会引入任何开销。

答案 2 :(得分:0)

放置new的存在是为了使显式构造函数调用可以定位到任意缓冲区(对于自定义分配器,调试等等)。就是这样。

您可以自己编写验证其输入的内容。

例如:一个类可能需要某种对齐,你怀疑有一些自定义分配器捏造它。因此,您为该类提供了一个不同的新位置,并查看当所述分配器使用它时会发生什么。

答案 3 :(得分:0)

您似乎认为该函数可以某种方式验证它传递的指针。

它不能。语言标准中没有任何内容允许这样做。当然,检查nullptr案例是可能的,但只是略有用处。

对齐错误严格来说是UB,因此任何实现都可以自由地执行任何操作。 (即使只是让它工作:x86)

检查内存区域是否足够大,特别是对于新的放置没有任何意义,因为用户代码很可能也会将其他内容放入该区域,并且编译器无法检查它。除了C和C ++之外,还无法检查mem的已分配区域的大小。