Подтвердить что ты не робот

Как инициализировать shared_ptr, который является членом класса?

Я не уверен в хорошем способе инициализации shared_ptr, который является членом класса. Можете ли вы сказать мне, подходит ли способ, который я выбираю в C::foo(), или есть лучшее решение?

class A
{
  public:
    A();
};

class B
{
  public:
    B(A* pa);
};

class C
{
    boost::shared_ptr<A> mA;
    boost::shared_ptr<B> mB;
    void foo();
};

void C::foo() 
{
    A* pa = new A;
    mA = boost::shared_ptr<A>(pa);
    B* pB = new B(pa);
    mB = boost::shared_ptr<B>(pb);
}
4b9b3361

Ответ 1

Ваш код верен (он работает), но вы можете использовать список инициализации, например:

C::C() :
  mA(new A),
  mB(new B(mA.get())
{
}

Что еще правильнее и безопаснее.

Если по какой-либо причине броски new A или new B, у вас не будет утечки.

Если new A выбрасывается, тогда память не выделяется, и исключение также прерывает ваш конструктор. Ничего не было построено.

Если new B выбрасывает, и исключение все равно прервет ваш конструктор: mA будет правильно разрушено.

Конечно, поскольку для экземпляра B требуется указатель на экземпляр A, порядок объявления членов имеет значение.

Правило объявления элемента корректно в вашем примере, но если оно было отменено, ваш компилятор, вероятно, пожаловался бы на mB be инициализировался до mA, и создание экземпляра mB скорее всего потерпит неудачу (поскольку mA не будет сконструирован, поэтому вызов mA.get() вызывает поведение undefined).


Я также предложил бы использовать shared_ptr<A> вместо A* в качестве параметра для вашего конструктора B (, если он вызывает чувства, и если вы можете принять небольшие накладные расходы), Вероятно, это было бы безопаснее.

Возможно, гарантировано, что экземпляр B не может жить без экземпляра A, а затем мой совет не применяется, но здесь нам не хватает контекста, чтобы дать окончательный совет относительно этого.