【问题标题】:How to initialize a shared_ptr that is a member of a class?如何初始化作为类成员的 shared_ptr?
【发布时间】:2011-04-02 12:10:03
【问题描述】:

我不确定初始化作为类成员的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);
}

【问题讨论】:

  • chubsdad:在成员中不起作用,仅在 ctors 中起作用。
  • @MSalters:我不知道你想说什么。
  • 在最初的问题中,我说的是函数 foo(),而不是构造函数。所以初始化列表不适合。
  • 虽然在构造函数中初始化成员通常更好,但您的代码仍然有效。但是你到底在问什么?

标签: c++ boost initialization shared-ptr member


【解决方案1】:

您的代码非常正确(可以正常工作),但您可以使用初始化列表,如下所示:

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

哪个更正确,更安全。

如果出于某种原因,new Anew B 抛出,您将没有泄漏。

如果new A 抛出,则不会分配内存,并且异常也会中止您的构造函数。什么都没有构建。

如果new B 抛出,并且异常仍将中止您的构造函数:mA 将被正确销毁。

当然,因为B 的实例需要一个指向A 实例的指针,所以成员的声明顺序很重要

您的示例中的成员声明顺序是正确的,但如果它被颠倒了,那么您的编译器可能会抱怨 mBmA 之前初始化并且 mB 的实例化可能会失败(因为 mA尚未构造,因此调用 mA.get() 会调用未定义的行为)。


我还建议您使用 shared_ptr&lt;A&gt; 而不是 A* 作为 B 构造函数的参数(如果这是有道理的,如果您可以接受少量开销) .可能会更安全。

也许可以保证,如果没有 A 的实例,B 的实例就无法生存,然后我的建议不适用,但我们在此缺乏上下文来就此给出明确的建议。

【讨论】:

  • 鉴于你是依赖它,所以值得一提的是成员的构造顺序是如何工作的,以及所涉及的序列点。
  • @ereOn - 构造函数的返回类型?
  • @DumbCoder:从错误的问题中复制。我修好了。
  • @MSalters:如果mB 的初始化程序包括调用mA.get()(确实如此),那么初始化的顺序非常重要。
  • @MSalters:只是为了清楚我最初的意思:虽然答案是正确的,但还没有完全清楚为什么它是正确的。如果 mAmB 的声明顺序在类定义中颠倒了,那么可能不清楚为什么 C() : mA(new A), mB(new B(mA.get())) {} 不正确。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多