构造函数初始化列表中的共享参数

Shared argument in constructor initializer list

我有这个类:

class A
{
public:
    A(std::shared_ptr<SomeClass> p);
private:
    std::shared_ptr<SomeClass> _p;
};

class B
{
public:
    B(std::shared_ptr<SomeClass> p);
private:
    std::shared_ptr<SomeClass> _p;
};

class Foo
{
public:
    Foo();
private:
    A _a;
    B _b;
};

来自 AB 的两个构造函数参数共享相同的指针引用 shared_ptr。在这种情况下:

我很困惑,因为两个 类 都需要相同的 shared_ptr 实例,所以我必须将该指针存储在某个地方,我认为初始化列表不可能做到这一点。

此外,如果初始化发生在构造函数的主体中,则意味着 AB 都应该有一个 move 构造函数,对吗?因为我必须做这样的事情:

Foo::Foo() //: Cannot use initializer list
{
    auto ptr = std::make_shared<SomeClass>(SomeClass());
    _a = A(ptr);
    _b = B(ptr);
}

您不能在构造函数的主体中初始化成员。当主体开始执行时,成员必须已经初始化。因此,如果您尝试这样做,成员将被默认构造,然后您将只是分配给他们。 AB 没有默认构造函数,因此无法编译。

如果您负担得起增加尺寸,请将 shared_ptr 也设为 Foo 的成员并使用它。

class Foo {
public:
    Foo(): _ptr(std::make_shared<SomeClass>()), _a(_ptr), _b(_ptr) {}
private:
    std::shared_ptr<SomeClass> _ptr;
    A _a;
    B _b;
};

鉴于您定义 类 的方式(即无法访问内部 shared_ptr),我认为您的解决方案很好。但请注意 AB 将需要默认构造函数。这就是它们在进入构造函数体之前的初始化方式。

此外,一旦进入构造函数体,您将进行赋值。所以 AB 都需要一个赋值运算符。

此外,我觉得将 std::shared_ptr 作为引用传递给函数(包括构造函数)是一种很好的做法。

其实我想到了更好的解决办法。创建 shared_ptr,然后委托给将使用它来构造 _a_b 的私有构造函数。 (感谢 Zan Lynx 建议使用函数参数作为临时存储。)

class Foo {
public:
    Foo(): Foo(std::make_shared<SomeClass>()) {}
private:
    Foo(std::shared_ptr<SomeClass> ptr): _a(ptr), _b(ptr) {}
    A _a;
    B _b;
};