Как использовать std :: nothrow и std :: new_handler в стандартном заголовочном файле & lt; new & gt;

Наткнулся на небольшой стандартный заголовочный файл <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++ блок?

3

Решение

nothrow_t используется, чтобы сказать operator new работать в обратно совместимом режиме «вернуть ноль при ошибке, а не выбрасывать исключение».

То есть, если вы видите такой код:

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

это было бы nothrow_t на работе. Для соответствующих разделов в стандарте начните с (по состоянию на C ++ 11 N3376) 17.6.4.6 [replace.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_handler а также set_new_handler выше) явно не нужно аннотировать, чтобы иметь внешнюю связь, потому что они имеют внешнюю связь по умолчанию.

  2. new_handler используется, когда пользователь переопределяет значение по умолчанию operator new используется по телефону set_new_handler, Это просто тип указателя на функцию.

  3. Вероятно, потому что подписи operator new не зарезервированы в C. extern "C++" сообщает компилятору, что ему разрешено выполнять манипулирование именами и другие специфические для C ++ функции для этих функций. Таким образом, вы можете скомпилировать один модуль перевода как C, а другой — как C ++, и связать их вместе в одном двоичном файле, не беспокоясь о том, что кто-то в C определил функцию, конфликтующую с компилятором. operator new,
4

Другие решения

Ну, это действительно вопрос «прочитай документацию, пожалуйста». Любая хорошая вводная книга по C ++ должна обсуждаться nothrow, Например, «язык программирования C ++» Бьярне, как я помню, делает.

Но в любом случае вы используете nothrow превратить std::bad_alloc исключения в результатах нулевого указателя, и вы используете новый обработчик возможно повторить неудачное распределение.

На практике не забудьте поставить :: перед new когда вы используете nothrow и вообще при использовании глобального размещения новых, чтобы избежать подбора новых размещения из классов. За исключением того, что в целом следует избегать размещения новых (как это очень низкоуровневая функция языка), я бы сделал это даже когда это технически не имеет смысла. Так же, как хорошая привычка.


Пример:

#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 \ тест]
> а
Распределение не удалось!

[D: \ DEV \ тест]
> _

Обратите внимание, что вышеприведенное предполагает 32-битный процесс 🙂

2

По вопросам рекламы [email protected]