Исключительная безопасность с конструктором shared_ptr

В Эффективный C ++ 3 / E, Я прочитал это:

Это исключительный небезопасный код:

class Test { };
void foo(const std::shared_ptr<Test> &ptr, int i);
int bar();
...

foo(std::shared_ptr<Test>(new Test), bar());

Потому что компилятор может реализовать так:

  1. бежать new Test
  2. вызов bar() <- если bar() выдает исключение, объект Test выделено new Test не может быть удалено
  3. вызов конструктора std::shared_ptr<Test>
  4. вызов foo()

Но в этом случае компилятор может знать, что есть утечка памяти. Компилятор не может сделать delete автоматически, если выдается исключение?

Кроме того, компилятор делает автоматически delete в таком случае:

Test *p = new Test;

это реализовано так:

  1. вызов operator new выделить память
  2. вызов конструктора Test, Если конструктор выдает исключение, память автоматически удаляется.

Почему компилятор не работает в первом случае, в отличие от второго?

3

Решение

Компилятор обычно не может знать, что произошла утечка памяти.
Как только код возвращается из конструктора Test,
Компилятор должен предположить, что объект был полностью и
правильно построено, что может (и часто так) означает, что
конструктор где-то зарегистрировал указатель на него, и
этот другой код будет ожидать, чтобы найти его.

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

Стандарт также мог бы наложить строгий порядок на
оценка выражения. Это уберет много проблем
неопределенного поведения, и сделать код более детерминированным (так
тесты более надежные). Исторически C не принимал это
маршрут из-за его влияния на оптимизацию; C ++ сохранил
править.

4

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


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