为什么make_shared不能构造此对象?

时间:2019-05-30 11:10:09

标签: c++

尝试创建指向对象的共享指针时,我遇到此错误

True

我收到了构建时间错误

#include <iostream>
#include <vector>

class Foo {
public:
    std::shared_ptr<Foo> getFoo(int i) {
        auto foo = std::make_shared<Foo>(i);
        //auto foo = std::shared_ptr<Foo>(new Foo(i)); "works"
        return foo;
    }
protected:
    Foo(int i) {std::cout << "foo" << std::endl; }
};

int main(int argc, const char * argv[]) {

}

我可以通过将构造函数设为私有来避免这种情况,但是我想知道为什么make_shared失败并且shared_ptr(new)有效吗?

2 个答案:

答案 0 :(得分:2)

//auto foo = std::shared_ptr<Foo>(new Foo(i)); "works"

在这里您可以从Foo内部访问Foo的构造函数,然后将此指针传递给std::shared_ptr,这很好。

auto foo = std::make_shared<Foo>(i);

这里std::make_shared尝试访问Foo的{​​{1}}的构造函数,因此是不允许的。

答案 1 :(得分:2)

@SombreroChicken提供了一个很好的答案,说明为什么是这种情况。 我想提供一个可能的解决方案

#include <iostream>
#include <memory>

class Foo {
private:
    struct Token{};
public:
    std::shared_ptr<Foo> getFoo(int i) {
        auto foo = std::make_shared<Foo>(i, Token{});
        //auto foo = std::shared_ptr<Foo>(new Foo(i)); "works"
        return foo;
    }
    Foo(int i, Token) : Foo(i) {}

protected:
    Foo(int i) {std::cout << "foo" << std::endl; }
};

int main(int argc, const char * argv[]) {

}

通过创建仅需要Foo才能完成的公共构造函数来工作,因此任何收到“令牌”的人都可以调用该构造函数

注意:传递此类标记参数最好作为第一个参数,因为

  1. 与标准库保持一致

  2. 某些编译器(特别是msvc)对其进行了特殊处理,从而缩短了编译时间