Инициализация переменной-члена 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 не допускаются:

  1. Если вы получаете голый указатель, выделенный кем-то другим, и сохраняете его в shared_ptr, Это часто имеет место при взаимодействии с C API.
  2. Если конструктор, который вы хотите вызвать, не является общедоступным (make_shared можно только вызывать публичных конструкторов). Это может произойти с фабричными функциями, когда вы хотите заставить пользователей создавать объект с фабрики.

    Однако есть способы обойти это. Вместо того, чтобы иметь частный конструктор, есть публичный конструктор. Но заставить конструктор принимать тип с может быть создан только теми, кто имеет частный доступ к классу. Таким образом, единственные люди, которые могут позвонить make_shared с этим типом объекта те, которые имеют частный доступ к классу.

Так что да, вы можете сделать это.

В этом случае, используя make_shared это не просто разрешено, но лучше использовать его. Если вы используете new, он будет выделять память для вашего клиента где-то, а затем память для вашего shared_ptr где-то еще, сохраняя как сильные, так и слабые ссылки (для слабых указателей и общих указателей). Если вы используете make_shared у вас будет только одно место в памяти со всем и, следовательно, только одно новое.

Я не уверен, что мне было действительно ясно, это было целью GotW # 103, прочитайте это, это хорошо объяснено там.

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