Я знаю, что довольно много C++ часто задаваемых вопросов (и ответы здесь на SO) говорят, что нет необходимости проверять возвращаемое значение простого нового выражения для null, так как простое новое -expression указывает на сбои, бросая исключения. В основном они утверждают, что простое новое выражение никогда не возвращает null. (Под «простым новым выражением» я подразумеваю новое выражение, которое не является номером nothrow
).Пользовательский оператор new, который возвращает нулевой указатель
Однако, несмотря на это, это очень простой вопрос, я вдруг понял, что не понимаю, какие конкретные предположения они делают (если они есть), когда они дают ответ.
В частности, я задаюсь вопросом, могу ли я перегрузить базовую формуляр ::operator new
, чтобы всегда возвращать нулевой указатель и, следовательно, ожидать, что все простые новые выражения, которые используют этот оператор, также вернут нулевые указатели.
В соответствии с языковой спецификацией, если мой ::operator new
объявлен как неброска, я могу/должен указывать на отказ выделения памяти, возвращая нулевой указатель. Итак, давайте просто
void *operator new(size_t s) throw() {
return 0;
}
int main() {
int *i = new int;
}
В моих экспериментах над новым выражением не успешно возвращает нулевой указатель. Итак, я нарушаю какие-либо правила в приведенном выше коде или нет? Является ли законным объявлять простой ::operator new
как не метательный?
А если приведенный выше код в порядке, то я предполагаю, что когда кто-то заявляет, что простой новый «никогда не возвращает нулевой указатель», они делают это в предположении, что версия ::operator new
, предоставленная стандартной библиотекой, не была заменены. Правильно ли это презумпция?
Есть еще один аспект этого обсуждения - даже если стандарт явно разрешает вам возвращать 'nullptr' /' 0', как вы сказали, это стандартные библиотеки, необходимые для обработки '0' s? Я бы поспорил, что это не так, а реализации нет, поэтому было бы непрактичным писать программу с возвратом 0. :: operator new. 20.8.9.1/4 требует 'std :: allocate :: allocate' throw' std :: bad_alloc', если невозможно получить хранилище - будет ли он (как правило, избыточно) проверять значение null или доверять ':: operator new' для броска? –
Не нужна ли другая версия, не имеющая метательных версий, новая? 'void * operator new (std :: size_t size);' не может возвращать нулевой указатель, он должен бросать в случае ошибки, даже если он переопределен. – user657267
Стандартная библиотека будет использовать ':: new T' для стандартной конструкции и' :: new (static_cast (get_allocator() (1)) T' для размещения, и эти формы всегда вызывают функцию выделения метаданных (независимо от того, был заменен). –