C++ c++;共享ptr不提供呼叫接线员

C++ c++;共享ptr不提供呼叫接线员,c++,constructor,shared-ptr,smart-pointers,C++,Constructor,Shared Ptr,Smart Pointers,我有一个类Foo,它包含一个Foo2类的shared_ptr,作为成员变量。我是这样宣布这句话的: class Foo{ public: Foo(); private: shared_ptr<Foo2> f2; }; 因为Foo2的唯一构造函数有3个参数。但是,这显示了一个错误,即: 类型“共享”不提供呼叫接线员 这不是创建类的共享指针实例的方法吗?这就是您想要做的: Foo::Foo() : f2(make_shared<Foo2>(a, b, c

我有一个类
Foo
,它包含一个
Foo2
类的
shared_ptr
,作为成员变量。我是这样宣布这句话的:

class Foo{
public:
    Foo();

private:
    shared_ptr<Foo2> f2;

};
因为Foo2的唯一构造函数有3个参数。但是,这显示了一个错误,即:

类型“共享”不提供呼叫接线员


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

这就是您想要做的:

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

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

如果
a
b
c
仅在构造函数中创建,则必须重新分配
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);
f2.重置(新的Foo2(a,b,c));
f2=标准::共享的ptr(新的Foo2(a、b、c));
f2=标准::使_共享(a、b、c);
a、 b和c是在Foo()本身中创建的变量

然后使用赋值运算符:

Foo::Foo() {
    f2 = std::make_shared<Foo2>(a, b, c);
}
Foo::Foo(){
f2=标准::使_共享(a、b、c);
}
通过执行f2(…);您正在调用方法为
f2.operator()(…)
您需要做的是在

或者使用在构造函数体中创建它(此方法隐藏新运算符)

Foo::Foo()
{
f2=标准::使_共享(a、b、c);
}

您的构造函数实现不正确

语句
f2(新的Foo2(a,b,c))
没有初始化成员
f2
。它试图将其当作一个函数来使用(例如,调用接受
Foo2*
操作符()
)。编译错误是因为
std::shared_ptr
没有这样的运算符

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

Foo::Foo(): f2(new Foo2(a, b, c))
{
}
这假设
a
b
c
之前已声明(以编译器可见的方式)并已初始化


如果在构造函数主体中初始化了
a
b
c
,则需要执行以下操作

Foo::Foo()
{
   //  define and initialise a,b,c
   f2 =  std::make_shared<Foo2>(a, b, c);
}
Foo::Foo()
{
//定义并初始化a、b、c
f2=标准::使_共享(a、b、c);
}
这实际上相当于

Foo::Foo() : f2()
{
   //  define and initialise a,b,c
   f2 =  std::make_shared<Foo2>(a, b, c);
}
Foo::Foo():f2()
{
//定义并初始化a、b、c
f2=标准::使_共享(a、b、c);
}

在这两种形式中,在输入
Foo
s构造函数块之前,调用了
f2
(不接受任何参数)的默认构造函数。语句
f2=std::make_shared(a,b,c)
构造另一个对象并执行移动赋值(假定已构造
f2
),而不是初始化

a
b
c
需要在以下情况之前计算初始化器列表中初始化它的备选方案:

  • 使用lambda直接调用(也可能是自由函数)

    Foo::Foo():f2([]()
    {
    //创建并计算参数a、b和c
    返回std::使_共享(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)))
    {}
    
    Foo::Foo():Foo(ComputeABC()){
    Foo::Foo(std::tuple t):
    f2(标准::使_共享(标准::获取(t)),
    标准::get(t),
    std::get(t)))
    {}
    

只需使用构造函数的初始值设定项列表:
Foo::Foo():f2(新的Foo2(a,b,c)){}
首先,
f2将使用默认构造函数初始化;第二个
f2(新的Foo2(a,b,c))
根本不是初始化,它是试图调用
f2
对象的
操作符()
;第三-执行实际初始化
Foo::Foo():f2{::std::make_shared(a,b,c)}{}
条b(某物;
b(某物)
是非常不同的东西,即使它们表面上看起来很相似。@VTT它声明了一个指向堆栈的智能指针否?@user7331538那么你需要分配。请发布一段真实代码,而不是向我们提供假代码。显然OP不能这样做。@πάνταῥεῖ 请参阅编辑。似乎你的表现比其他答案要好。这就是为什么我不回答这些不完整的问题,而试图成为FGITW。@πάνταῥεῖ 我很好,当我发布我的答案时,答案是零。但是我的答案错了吗?我碰巧认为你的答案是最正确的。所有其他人都在鼓励重复默认构造。
Foo::Foo(){
//create and calculate parameters a, b and c
f2(new Foo2(a, b, c));
}
Foo::Foo(): f2(new Foo2(a, b, c))
{
}
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);
}
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)))
{}