Инициализация переменной-члена shared_ptr, новая против make_shared?
При инициализации переменной-члена shared_ptr:
// .h
class Customer
{
public:
Customer();
private:
std::shared_ptr<OtherClass> something_;
}
// .cpp
Customer():
something_(new OtherClass())
{
}
против
Customer():
something_(std::make_shared<OtherClass>())
{
}
Разрешена ли версия make_shared? Мне всегда кажется, что я вижу первую версию, которая предпочтительнее?
2 ответа
Единственный раз, когда make_shared
не допускаются:
- Если вы получаете голый указатель, выделенный кем-то другим, и сохраняете его в
shared_ptr
, Это часто имеет место при взаимодействии с C API. Если конструктор, который вы хотите вызвать, не является общедоступным (
make_shared
можно только вызывать публичных конструкторов). Это может произойти с фабричными функциями, когда вы хотите заставить пользователей создавать объект с фабрики.Однако есть способы обойти это. Вместо того, чтобы иметь частный конструктор, есть публичный конструктор. Но заставить конструктор принимать тип с может быть создан только теми, кто имеет частный доступ к классу. Таким образом, единственные люди, которые могут позвонить
make_shared
с этим типом объекта те, которые имеют частный доступ к классу.
Так что да, вы можете сделать это.
В этом случае, используя make_shared
это не просто разрешено, но лучше использовать его. Если вы используете new, он будет выделять память для вашего клиента где-то, а затем память для вашего shared_ptr где-то еще, сохраняя как сильные, так и слабые ссылки (для слабых указателей и общих указателей). Если вы используете make_shared
у вас будет только одно место в памяти со всем и, следовательно, только одно новое.
Я не уверен, что мне было действительно ясно, это было целью GotW # 103, прочитайте это, это хорошо объяснено там.