Private constructor and make_shared

后端 未结 3 1551
生来不讨喜
生来不讨喜 2021-01-06 20:34

I have a singleton class with a private constructor. In the static factory method I do the following:

shared_ptr MyClass::GetInstance()
{
             


        
相关标签:
3条回答
  • 2021-01-06 21:16

    You should use Meyers singleton instead. You should ensure that your compiler supports C++11 magic static before.

    0 讨论(0)
  • 2021-01-06 21:21

    Please take VTT's comment seriously.


    To your question:

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

    The new is actually used within a lambda in a member-function; Well, A lambda defines a local-class, and C++ standards permits a local-class within a member-function to access everything the member-function can access. And its trivial to remember that member functions can access privates..

    std::make_shared has no access to the privates of MyClass. It's outside the scope of MyClass


    Example:

    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;
    }
    
    0 讨论(0)
  • 2021-01-06 21:41
    1. As mentioned, std::make_shared or its component parts don't have access to private members.

    2. the call_once and once_flag are un-necessary. They are implicit in c++11 static initialisation,

    3. You normally would not want to expose the shared pointer.

     

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

    However, there is one case I can imagine where you would want to expose a shared pointer to the impl - this is in the case where the class can choose to 'break off' or 'reset' the impl to a new one. In this case I would consider code like this:

    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));
    
        }  
    };
    

    However, in the end, it is my view that 'staticness' of a class should be an implementation detail, and unimportant to the user of the 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)
    {
    
    }
    
    0 讨论(0)
提交回复
热议问题