在标准头文件<new> </new>中使用std :: nothrow和std :: new_handler有什么用?

时间:2012-11-22 05:10:02

标签: c++ std nothrow

我遇到了一个小标准头文件<new>。我以前可能没有看到它的直接使用。对于那些感兴趣的人,这里是the g++ version

以下是我感兴趣的部分:

  struct nothrow_t { };
  extern const nothrow_t nothrow;
  /** If you write your own error handler to be called by @c new, it must
   *  be of this type.  */
  typedef void (*new_handler)();
  /// Takes a replacement handler as the argument, returns the previous handler.
  new_handler set_new_handler(new_handler) throw();
  1. 程序员如何使用struct nothrow_t及其对象nothrow?是个 对象真的需要extern
  2. new_handler何时使用?
  3. 为什么所有operator new/delete都在extern C++块中声明?

2 个答案:

答案 0 :(得分:4)

nothrow_t用于告诉operator new在向后兼容的“失败时返回null而不是抛出异常”模式下运行。

也就是说,如果你看到这样的代码:

int * idx = new(std::nothrow) int;

在工作中nothrow_t。对于标准中的相关部分,从(从C ++ 11 N3376开始)17.6.4.6 [replacement.functions] / 1开始,并从那里开始。

回答您的具体问题:

  1. 是的,它确实必须是外部的,至少根据18.6 [support.dynamic] / 1,其中包括:

    namespace std {
        class bad_alloc;
        class bad_array_new_length;
        struct nothrow_t {};
        extern const nothrow_t nothrow;
        typedef void (*new_handler)();
        new_handler get_new_handler() noexcept;
        new_handler set_new_handler(new_handler new_p) noexcept;
    }
    

    此外,17.6.2.3 [using.linkage] / 1表示“C ++标准库中的实体具有外部链接(3.5)”。函数和类(例如上面的get_new_handlerset_new_handler)没有明确需要注释以具有外部链接,因为它们默认具有外部链接。

  2. 当用户通过调用new_handler覆盖正在使用的默认operator new时,会使用
  3. set_new_handler。它只是一个函数指针类型。

  4. 可能是因为operator new的签名未在C中保留。extern "C++"告诉编译器允许对这些函数执行名称修改和其他C ++特定事务。通过这种方式,您可以将一个转换单元编译为C,将一个转换为C ++,并将它们链接在同一个二进制文件中,而不必担心C land中的某个人定义了与编译器的operator new冲突的函数。

答案 1 :(得分:2)

嗯,这真是一个“请阅读文档,请”的问题。任何关于C ++的好的入门书都应该讨论nothrow。例如,正如我记得的那样,Bjarne的“The C ++ Programming Language”确实如此。

但无论如何,您使用nothrowstd::bad_alloc个异常转换为nullpointer结果,并使用新处理程序来重试失败的分配。

实际上,当您使用::功能时,请务必将new放在nothrow前面,一般情况下使用全局展示位置时,请避免挑选从课程中添加新内容。除了通常应该避免放置new(因为它是非常低级的语言特性),即使它在技术上没有意义,我也会这样做。这是一个好习惯。


示例:

#include <iostream>     // std::wcout, std::endl
#include <stdlib.h>     // EXIT_FAILURE, EXIT_SUCCESS
#include <new>          // std::nothrow
using namespace std;

int main()
{
    int* const p = ::new( std::nothrow ) int[0x7fffffff/sizeof(int)];
    if( !p )
    {
        cout << "Allocation failed!" << endl;
        return EXIT_FAILURE;
    }
    cout << "Alles success!" << endl;
    delete[] p;
    return EXIT_SUCCESS;
}

我的系统输出:


[D:\dev\test]
> a
Allocation failed!

[D:\dev\test]
> _

请注意,上面假设是32位进程:)