Почему у boost нет make_scoped()?
Boost make_shared()
функция promises должна быть исключающей безопасность при попытке создать shared_ptr
.
Почему нет эквивалента make_scoped()
? Есть ли общая передовая практика?
Вот пример кода из boost::scoped_ptr
документации, который кажется мне небезопасным:
boost::scoped_ptr<Shoe> x(new Shoe);
Эта строка кода сделает эти три вещи в порядке:
- Выделить память кучи для
Shoe
- Вызов конструктора для
Shoe
- Вызов конструктора для
boost::scoped_ptr<Shoe>
Если конструктор для Shoe
выдает исключение, будет потеряна память . (см. R. Martinho Fernandes). scoped_ptr
не будет обрабатывать освобождение, потому что он не был построено еще.
Это надзор? Или есть решение, которое я не заметил?
Ответы
Ответ 1
Если конструктор выходит из строя, утечка памяти не происходит. Эта часть семантики new
, никаких интеллектуальных указателей:
struct Foo { Foo() { throw 23; } };
new Foo(); // no memory leaked
Добавленная безопасность исключений, предоставляемая make_shared
, возникает, когда вы инициализируете два shared_ptr
в выражении, а две инициализации не секвенированы, как это имеет место в аргументах вызова функции:
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))
, может случиться следующее:
-
new Bar(false)
оценивается и преуспевает: выделена память;
-
new Bar(true)
оценивается и терпит неудачу: он не утечки памяти в результате этой оценки;
В это время не было построено shared_ptr
, и поэтому память, выделенная в # 1, теперь просочилась.
Ответ 2
scoped_ptr
предшествует перемещению семантики и не поддается обработке по дизайну. Таким образом, make_scoped
было бы невозможно реализовать, потому что для возврата объекта из функции его тип должен быть подвижным или скопированным.
Ответ 3
Если Shoe бросает, то Чистка не построена, поэтому ничего не может сделать scoped_ptr. Нет?
Scoped_ptr x находится в стеке и будет очищен при выходе из области.