Подтвердить что ты не робот

Как мне вызывать нечерную версию удаления?

У меня есть следующий код, который не компилируется:

int *p = new(nothrow) int;
delete (nothrow) p; //Error

Ошибка, которую я получаю:

ошибка C2440: 'delete': невозможно преобразовать из 'const std:: nothrow_t' в 'void *'

Существует ли версия nothrow delete? Если да, как я могу его вызвать?


В С++: полный справочник, он дал понять, что он существует, но я видел разные мнения в Интернете, поэтому путаница.

MSDN также говорит о его существовании, но я не мог найти, как его можно использовать в коде.

Здесь, некоторые люди говорят, что такой вещи нет.

4b9b3361

Ответ 1

A std::nothrow_t существует функция освобождения, но вы не можете вызвать ее с выражением delete.

Функция дезадаптации существует для полноты. Если выражение new терпит неудачу из-за исключения, компилятор должен освободить выделенную память через operator new с помощью соответствия на operator delete. Таким образом, должен быть operator delete, который принимает std::nothrow_t, чтобы это разрешить.

(То есть, в общем случае выражение new с формой new (args...) T будет выделять память с вызовом operator new(sizeof(T), args...). To "match" означает вызов operator delete с теми же аргументами, кроме первого.)

Обратите внимание, что вы можете напрямую вызвать оператора: operator delete(memory, std::nothrow);. Однако выражение delete никогда не вызывает глобальную функцию освобождения с дополнительными параметрами.


Итак, вы можете "вызвать" его с помощью:

struct always_throw
{
    always_throw() { throw std::exception(); }
};

new (std::nothrow) always_throw;

В какой-то момент это распределит память с вызовом:

void* __memory = operator new(sizeof(always_throw), std::nothrow);

Поскольку инициализация объекта бросает, компилятор должен освободить выделенную память с помощью соответствующей функции освобождения, поэтому он выполняет следующие действия:

operator delete(__memory, std::nothrow);

Вызов версии std::nothrow_t.

Ответ 2

Нет такой формы delete, потому что delete не выбрасывает, так как:

  • Он не выполняет никаких распределений.
  • Он часто используется в деструкторах, которые не должны бросать!

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

Ответ 3

Для большинства практических целей существует только одна версия удаления. new(nothrow) записывается как новый оператор размещения, но по большей части нет соответствующей версии для удаления. Единственное исключение - это версия delete, которая вызывается, когда новое место размещения выбрано, но поскольку (в этом случае) вы уверены, что new не может выбрасывать, эта версия удаления не имеет реального использования /help здесь.