Избегайте std :: bad_alloc. new должен возвращать NULL-указатель - PullRequest
5 голосов
/ 10 ноября 2009

Я портирую приложение среднего размера с C на C ++. Это нигде не касается исключений, и это не должно измениться.

Мое (неправильное!) Понимание C ++ было (пока я вчера не усвоил трудный путь), что (по умолчанию) оператор new возвращает указатель NULL в случае проблемы выделения. Однако это было верно только до 1993 года (или около того). В настоящее время он генерирует исключение std :: bad_alloc.

Можно ли вернуться к старому поведению, не переписывая все для использования std :: nothrow при каждом отдельном вызове?

Ответы [ 5 ]

11 голосов
/ 10 ноября 2009

Вы можете перегрузить оператор new:

#include <vector>

void *operator new(size_t pAmount) // throw (std::bad_alloc)
{
    // just forward to the default no-throwing version.
    return ::operator new(pAmount, std::nothrow);
}

int main(void)
{
    typedef std::vector<int> container;

    container v;
    v.reserve(v.max_size()); // should fail
}
3 голосов
/ 10 ноября 2009

Включить заголовок <new>. Он содержит новую версию «без броска», которую вы можете использовать следующим образом:

#include <new>

int main() {
    int* p = new(std::nothrow) int;
    if (p) {
        delete p;
    }
}

Edit: Я признаю, что пропустил последнее предложение вопроса. Но, честно говоря, я думаю, что подстройка «обычного new» к нестандартному поведению тоже не очень хорошая идея. Я бы посмотрел на какой-нибудь автоматический поиск и замену, чтобы превратить каждый new в new(std::nothrow).

1 голос
/ 10 ноября 2009

Просто попробуйте:

1. Определите функцию, которую вы хотите вызвать из-за нехватки памяти.

2.Передайте эту функцию функции set_ new _handler, чтобы при возникновении ошибки вызываться эта функция.

1 голос
/ 10 ноября 2009

Извините, но, на мой взгляд, вы НЕ должны этого делать и возвращаться к старому новому поведению. Это потому, что вы все равно не можете избежать исключений.

Почему?

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

В книге Скотта Мейерса Эффективный C ++ это подробно обсуждалось, насколько я помню. Но я не уверен, что все дела рассмотрены (но я предлагаю достаточно их).

0 голосов
/ 10 ноября 2009

Ваш компилятор, вероятно, имеет переключатель командной строки, чтобы включить / отключить это поведение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...