3

我遇到了一个小的标准头文件<new>。我以前可能没有见过它的直接用途。这里是g++ 版本,供有兴趣的人使用。

以下部分是我感兴趣的:

  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++块中声明?
4

2 回答 2

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通过调用覆盖使用的默认值时使用set_new_handler. 它只是一个函数指针类型。

  3. 可能是因为operator newC 中没有保留的签名。extern "C++"告诉编译器允许对这些函数进行名称修改和其他 C++ 特定的事情。这样,您可以将一个翻译单元编译为 C,一个编译为 C++,并将它们链接到同一个二进制文件中,而不必担心 C 领域中的某个人定义了一个与编译器的operator new.
于 2012-11-22T05:28:33.833 回答
2

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

但无论如何,您使用nothrowstd::bad_alloc异常转换为空指针结果,并且您使用新的处理程序可能重试失败的分配。

作为一个实际的问题,记住在你使用该功能时将其放在::前面,并且一般在使用全局placement new时,以避免从classes中选择placement new。除了通常应该避免放置 new (因为它是非常低级的语言特性),即使它在技术上没有意义,我也会这样做。就像一个好习惯一样。newnothrow


例子:

#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:\开发\测试]
> 一个
分配失败!

[D:\开发\测试]
> _

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

于 2012-11-22T05:21:01.300 回答