私有构造函数和 make_shared

Private constructor and make_shared

我有一个带有私有构造函数的单例 class。在静态工厂方法中,我执行以下操作:

shared_ptr<MyClass> MyClass::GetInstance()
{
    static once_flag onceFlag;

    call_once(onceFlag, []() {
        if (_instance == nullptr)
            _instance.reset(new MyClass());
    });

    return _instance;
}

如果我用

_instance = make_shared<MyClass>();

代码无法编译。我的问题是:为什么 new 可以调用私有构造函数而 make_shared 不能?

请认真对待


针对您的问题:

My question is: why new can invoke a private constructor but make_shared not?

new 实际上在 成员函数 的 lambda 中使用;好吧,A lambda 定义了一个 local-class,而 C++ 标准 permits 定义了一个 local-classmember-function 中访问 member-function 可以访问的所有内容。记住成员函数可以访问私有是微不足道的..

std::make_shared 无法访问 MyClassprivates。它在 MyClass

的范围之外

示例:

class X{
    X(){};
public:
    static X* create(){ // This member-function can access private functions and ctors/dtor
        auto lm = [](){ // This lambda inherits the same access of enclosing member-function
               return new X();
        };
        return lm();
    }
};

int main(){
    auto x = X::create();    //valid;
    auto y = new X();        //invalid;
}

您应该改用 Meyers singleton。您应该确保您的编译器之前支持 C++11 magic static。

  1. 如前所述,std::make_shared或其组成部分无法访问私有成员。

  2. call_onceonce_flag 是不必要的。它们隐含在 c++11 静态初始化中,

  3. 您通常不想公开共享指针。

class MyClass
{
    MyClass() {}

public:
    static MyClass& GetInstance()
    {
        static auto instance = MyClass();
        return instance;
    }
};

但是,我可以想象在一种情况下您希望公开一个指向 impl 的共享指针 - 这种情况下 class 可以选择 'break off' 或 'reset' 一个新的暗示。在这种情况下,我会考虑这样的代码:

class MyClass2
{
    MyClass2() {};

    static auto& InternalGetInstance()
    {
        static std::shared_ptr<MyClass2> instance { new MyClass2 };
        return instance;
    }

public:

    static std::shared_ptr<MyClass2> GetInstance()
    {
        return std::atomic_load(std::addressof(InternalGetInstance()));
    }

    static void reset() {
        std::atomic_store(std::addressof(InternalGetInstance()),
                        std::shared_ptr<MyClass2>(new MyClass2));

    }  
};

然而,最后,我认为 class 的 'staticness' 应该是一个实现细节,对 class 的用户来说并不重要:

#include <memory>
#include <utility>

class MyClass
{
    // internal mechanics

    struct Impl {

        auto doSomething() {
            // actual implementation here.
        }
    };

    // getImpl now becomes the customisation point if you wish to change the
    // bahviour of the class later
    static Impl& getImpl() {
        static auto impl = Impl();
        return impl;
    }


    // use value semantics - it makes for more readable and loosely-coupled code
public:
    MyClass() {}

    // public methods defer to internal implementation

    auto doSomething() {
        return getImpl().doSomething();
    }
};


int main() {

    // note: just create objects
    auto mc = MyClass();
    mc.doSomething();

    // now we can pass the singleton as an object. Other functions don't even
    // need to know it's a singlton:

    extern void somethingElse(MyClass mc);
    somethingElse(mc);
}

void somethingElse(MyClass mc)
{

}