1

Considering the following design for singleton pattern from yolinux (http://www.yolinux.com/TUTORIALS/C++Singleton.html)

#include <string>

class Logger{
public:
   static Logger* Instance();
   bool openLogFile(std::string logFile);
   void writeToLogFile();
   bool closeLogFile();

private:
   Logger(){};  // Private so that it can  not be called
   Logger(Logger const&){};             // copy constructor is private
   Logger& operator=(Logger const&){};  // assignment operator is private
   static Logger* m_pInstance;
};

would someone explain why Logger(Logger const&){}; and Logger& operator=(Logger const&){}; are required here?
Thanks in advance.

  • Off topic: I would suggest you use [this](http://stackoverflow.com/questions/1008019/c-singleton-design-pattern) variation of the singleton pattern for C++ as it gets rid of the pointers. – niklasfi Apr 21 '14 at 09:35
  • Beware that the first implementation of the anti-pattern in that article isn't thread-safe. The one at the end is (under the C++11 memory model), but (as noted) has potentially disastrous lifetime issues. You might consider avoiding global variables (whether or not you disguise them as "singletons") in C++, even if you don't care about the [philosophical objections](http://stackoverflow.com/questions/137975) to invisible coupling; they are invariably more trouble than they're worth. – Mike Seymour Apr 21 '14 at 10:54

6 Answers6

3

If you force the copy constructor and the assignment operators to be private then you won't be able to compile assignment of two Logger objects.

This will result in a linker error, which is not an explicit message. These methods are generated by default so you have to force them to be private

In C++11 they use the deleted methods to have a clearer message

   Logger(Logger const&)=delete;             // copy constructor does not exist
   Logger& operator=(Logger const&)=delete;  // assignment operator does not exist

The delete is not compulsory and the singleton works well without this feature so if you don't have this supported in your compiler you can just make it private it will work. This feature gives explicit errror messages but does not affect the behaviour of the singleton itself.

For more info about delete feature you can have a look here:

Meaning of = delete after function declaration

You can also prevent the object from being destroyed by making the destructor private.

What is the use of having destructor as private?

Community
  • 1
  • 1
Gabriel
  • 3,564
  • 1
  • 27
  • 49
  • what about `delete` buddy? do I need to just to private the destructor? –  Apr 21 '14 at 10:57
  • added it into the answer but in one word it the delete feature is not compulsory – Gabriel Apr 21 '14 at 11:03
  • perfect, and what about removing the object, for example `Logger* l=Logger::Instance(); delete l;` does delete purge the object? so how can I prevent of deleting the object. Thanks. –  Apr 21 '14 at 12:20
1

From your link:

This design pattern and methodology ensures that only one instance of the C++ class is instantiated.

Logger(Logger const&) is a copy constructor which allows to copy object. And this is wrong by idea. Logger& operator=(Logger&) also allows to copy object.

Max Frai
  • 61,946
  • 78
  • 197
  • 306
1

The comments explain this quite nicely.

If you didn't explicitly define the constructor and copy constructor, then they will be created by default as public. By defining them here, you are making sure they are private, and so can never be called by the user.

Matt
  • 7,100
  • 3
  • 28
  • 58
1

The copy constructor and the lvalue assigment operator are declared as private to make the type non-copyable.

On the other hand I encourage you to use the Meyers singleton instead of the dynamic-memory based: Its far easier to implement, not leaks (Note being strict that your singleton leaks memory, the instance is never deleted), and is thread-safe as defined in the C++11 standard memory model:

T& instance()
{
    static T _instance;

    return _instance;
}
Manu343726
  • 13,969
  • 4
  • 40
  • 75
1

Those are copy constructor and copy assignment operator. If they weren't defined as private they would be automatically generated as public and the instance would be copyable which contradicts the Singleton pattern.

Since the C++11 standard you could also use:

Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;

this syntax is perhaps clearer and also ensures that the object can't be copied even by friends and private members.

Honza Brabec
  • 37,388
  • 4
  • 22
  • 30
1

The traditional solution to achieve singleton behavior is to declare constructor private. The copy constructor and assignment operator (which intentionally have no implementations) are declared private to prevent any sort of copies being made

•Because they are private, this will lead to a compile-time error from anyone trying to use them that has not access to the private parts of the class.

•Which leaves friends (and the class itself) for which the error will occur under the form of undefined symbol, either at link-time (if you check for those there) or most probably at run-time (when trying to load the library).

DNamto
  • 1,342
  • 1
  • 21
  • 42