Почему boost не имеет make_scoped()?

Повышение-х make_shared() функция обещает быть исключительной безопасностью при попытке создать shared_ptr,

Почему нет make_scoped() эквивалент? Есть ли распространенная лучшая практика?

Вот пример кода из boost::scoped_ptr документация, которая мне кажется небезопасной:

    boost::scoped_ptr<Shoe> x(new Shoe);

Эта строка кода будет выполнять эти три вещи по порядку:

  • Выделите кучу памяти для Shoe
  • Вызовите конструктор для Shoe
  • Вызовите конструктор для boost::scoped_ptr<Shoe>

Если конструктор для Shoe выдает исключение, память будет просочиться. (см. ответ Р. Мартиньо Фернандеса) scoped_ptr не будет обрабатывать освобождение, потому что оно еще не было построено.

Это недосмотр? Или есть решение, которое я не заметил?

3 ответа

Решение

Если конструктор дает сбой, память не просачивается. Это часть семантики new, не задействованы умные указатели:

struct Foo { Foo() { throw 23; } };
new Foo(); // no memory leaked

Добавленная исключительная безопасность, обеспеченная make_shared происходит, когда вы инициализируете два shared_ptrs в выражении, и две инициализации не упорядочены, как в случае аргументов вызова функции:

struct Bar {
    Bar(bool fail) {
        if(fail) throw 17;
    }
}
f(shared_ptr<Bar>(new Bar(true)), shared_ptr<Bar>(new Bar(false)));

Поскольку нет последовательности между оценками new Bar(true), shared_ptr<Bar>(new Bar(true)), new Bar(false) а также shared_ptr<Bar>(new Bar(false))может произойти следующее:

  1. new Bar(false) оценивается и успешно выполняется: память выделяется;
  2. new Bar(true) оценивается и дает сбой: он не теряет память в результате этой оценки;

нет shared_ptr был построен в это время, и поэтому память, выделенная в #1, теперь просочилась.

scoped_ptr предшествует движению семантики и не копируется по дизайну. Таким образом, make_scoped было бы невозможно реализовать, потому что для возврата объекта из функции его тип должен быть подвижным или копируемым.

Если Shoe бросает, то Shoe не создается, поэтому scoped_ptr ничего не может сделать. Нет? Scoped_ptr x находится в стеке и будет очищен при выходе из области видимости.

Другие вопросы по тегам