c++ shared_ptr 不提供调用运算符

c++ shared_ptr does not provide a call operator

我有一个classFoo,其中包含classFoo2shared_ptr作为成员变量。我这样声明上面的句子:

class Foo{
public:
    Foo();

private:
    shared_ptr<Foo2> f2;

};

首先,我可以做到以上几点吗?即不初始化 shared_ptr?

Foo 的默认构造函数中,我正在初始化这个 shared_ptr varaibale,如下所示:

Foo::Foo(){
    //create and calculate parameters a, b and c
    f2(new Foo2(a, b, c));
}

因为 Foo2 的唯一构造函数有 3 个参数。然而,这显示了一条错误消息:

Type 'shared_ptr<Foo2>' does not provide a call operator

这不是创建class的共享指针实例的方法吗?

这就是你想要做的:

Foo::Foo() : f2(make_shared<Foo2>(a, b, c)) {
}

您看到的错误消息意味着您使用的语法试图调用 Foo::operator()(A,B,C),即对象上的调用运算符。然而,在初始化期间,语法改为调用构造函数。

如果你坚持不初始化f2,你也可以这样做:

Foo::Foo() : f2(nullptr) {
   f2 = make_shared<Foo2>(a, b, c);
}

请注意,: f2(nullptr) 部分并非绝对必要。我包含它是为了显示默认情况下发生的情况。

如果abc只在构造函数中创建,则必须重新赋值f2。您不能在其声明或成员初始值设定项列表之外初始化变量(这是您尝试执行的操作)。

以下任何一个都可以:

f2.reset(new Foo2(a, b, c));
f2 = std::shared_ptr<Foo2>(new Foo2(a, b, c));
f2 = std::make_shared<Foo2>(a, b, c);

a, b and c are variables that are created in Foo() itself

然后使用赋值运算符:

Foo::Foo() {
    f2 = std::make_shared<Foo2>(a, b, c);
}

通过执行 f2(...);您将 operator() 方法调用为 f2.operator()(...); 您需要做的是在 initializer list

中初始化您的指针
Foo::Foo()
: f2(new Foo2(a, b, c))
{}

或者使用 std::make_shared 在你的构造函数中创建它(这个方法隐藏了 new 运算符)

Foo::Foo()
{
f2 = std::make_shared<Foo2>(a, b, c);
}

您的构造函数实现不正确。

Foo::Foo(){
//create and calculate parameters a, b and c
f2(new Foo2(a, b, c));
}

语句f2(new Foo2(a, b, c))没有初始化成员f2。它试图像使用函数一样使用它(例如调用接受 Foo2 *operator())。编译错误是因为std::shared_ptr<Foo2>没有这样的运算符

构造函数的更正确实现是使用初始化列表

Foo::Foo(): f2(new Foo2(a, b, c))
{
}

这假定 abc 之前已声明(以编译器可见的方式)并已初始化。

如果abc在构造函数体中初始化,则需要

Foo::Foo()
{
   //  define and initialise a,b,c
   f2 =  std::make_shared<Foo2>(a, b, c);
}

实际上相当于

Foo::Foo() : f2()
{
   //  define and initialise a,b,c
   f2 =  std::make_shared<Foo2>(a, b, c);
}

在任何一种形式中,f2 的默认构造函数(不接受任何参数)在进入 Foo 的构造函数块之前是 called/invoked。语句 f2 = std::make_shared<Foo2>(a, b, c) 构造另一个对象并执行移动赋值(假设 f2 已经构造)而不是初始化。

abc 需要在 initializer_list 之前计算时,在 initializer_list 中初始化它的备选方案:

  • 使用lambda直接调用(也可能是免费函数)

    Foo::Foo() : f2([]()
        {
            //create and calculate parameters a, b and c
            return std::make_shared<Foo2>(a, b, c);
        }())
    {}
    
  • 委托构造函数

    Foo::Foo() : Foo(ComputeABC()) {}
    
    Foo::Foo(std::tuple<int, int, int> t) :
        f2(std::make_shared<Foo2>(std::get<0>(t),
                                  std::get<1>(t),
                                  std::get<2>(t)))
    {}