-1

I am learning singleton design pattern and came across this piece of code

class Singleton
{
    private:
        static Singleton * pinstance_;
        static std::mutex mutex_;
    protected:
        static Singleton *GetInstance(const std::string& value);
};


Singleton* Singleton::pinstance_{nullptr}; //can this line be removed?
std::mutex Singleton::mutex_; //can this line be removed?

Singleton *Singleton::GetInstance(const std::string& value)
{
    std::lock_guard<std::mutex> lock(mutex_);
    if (pinstance_ == nullptr)
    {
        pinstance_ = new Singleton(value);
    }
    return pinstance_;
}

since pinstance_ and mutex_ are all members of Singleton class, they are accessible by GetInstance method. So my question is: can these two definition lines be removed?

  • 2
    Does this answer your question? [Why does a static data member need to be defined outside of the class?](https://stackoverflow.com/questions/18749071/why-does-a-static-data-member-need-to-be-defined-outside-of-the-class) – cpplearner Mar 11 '21 at 03:11
  • I don't follow your reasoning. Why would "accessible" imply that definitions are not needed? In fact, wouldn't the lack of a definition put something squarely in the "inaccessible because it does not exist" category? *You might have the start of valid reasoning if instead of "accessible" you had "needed by only" and instead of "removed" had "moved".* – JaMiT Mar 11 '21 at 04:47
  • @JaMiT: You're confusing definition with declaration. The definition only needs to exist in one place; code that wants to access them only needs to see the declaration (which is inside the `class {};`). It's not unreasonable to ask whether the compiler can invent a 0-initialized definition for something that's been declared; C++ does involve other cases where duplicate definitions get merged at link time. (e.g. for inline functions). Of course, I'm pretty sure this has already been asked and answered elsewhere by 2021. – Peter Cordes Mar 04 '22 at 04:40
  • @PeterCordes *"You're confusing definition with declaration."* -- No, I am not. A declaration alone is insufficient to make something exist. A declaration without a corresponding definition names something that does not exist, hence something that cannot be accessed because it does not exist (discovered at link time). -- *"C++ does involve other cases where duplicate definitions get merged at link time."* -- irrelevant as there is only one definition per name in the question. – JaMiT Mar 05 '22 at 05:41

1 Answers1

1

No, they can't be removed but they can be moved to local static variables of the method.

class Singleton
{
    protected:
        static Singleton *GetInstance(const std::string& value);
};

Singleton *Singleton::GetInstance(const std::string& value)
{
    static Singleton* pinstance_{nullptr};
    static std::mutex mutex_;

    std::lock_guard<std::mutex> lock(mutex_);
    if (pinstance_ == nullptr)
    {
        pinstance_ = new Singleton(value);
    }
    return pinstance_;
}

Also note, no guards required for initializing static variables. The compiler does it for you. Is local static variable initialization thread-safe in C++11? [duplicate]

Singleton *Singleton::GetInstance(const std::string& value)
{
    static Singleton* pinstance_ = new Singleton(value);
    return pinstance_;
}
273K
  • 29,503
  • 10
  • 41
  • 64
  • Thanks for your answer! If I just remove those two lines in my original post, WITHOUT adding them to GetInstance, does it still work? – GigiWithoutHadid Mar 11 '21 at 03:45