Наткнулся на небольшой стандартный заголовочный файл <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();
struct nothrow_t
и его объект nothrow
используются программистами? Этоextern
?new_handler
используемый ?operator new/delete
объявлены в extern C++
блок?nothrow_t
используется, чтобы сказать operator new
работать в обратно совместимом режиме «вернуть ноль при ошибке, а не выбрасывать исключение».
То есть, если вы видите такой код:
int * idx = new(std::nothrow) int;
это было бы nothrow_t
на работе. Для соответствующих разделов в стандарте начните с (по состоянию на C ++ 11 N3376) 17.6.4.6 [replace.functions] / 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
выше) явно не нужно аннотировать, чтобы иметь внешнюю связь, потому что они имеют внешнюю связь по умолчанию.
new_handler
используется, когда пользователь переопределяет значение по умолчанию operator new
используется по телефону set_new_handler
, Это просто тип указателя на функцию.
operator new
не зарезервированы в C. extern "C++"
сообщает компилятору, что ему разрешено выполнять манипулирование именами и другие специфические для C ++ функции для этих функций. Таким образом, вы можете скомпилировать один модуль перевода как C, а другой — как C ++, и связать их вместе в одном двоичном файле, не беспокоясь о том, что кто-то в C определил функцию, конфликтующую с компилятором. operator new
,Ну, это действительно вопрос «прочитай документацию, пожалуйста». Любая хорошая вводная книга по 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-битный процесс 🙂