Home Simple way to implement Singleton design pattern without using pointers in c++
Post
Cancel

Simple way to implement Singleton design pattern without using pointers in c++

A simple way to create a singleton design pattern

There are hell lot of example out there online, that how to create a singleton design pattern using pointer and static variable. But here I want to show you how can you create a singleton design pattern without even having a pointer in it. Looks amazing isn’t it?

Let’s dive directly into the coding. let say we have Student class below and we want to make it as a singleton. I know this example is not a best example for singleton. For simplicity let’s assume we want to make this Student class a singleton

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// Student.cpp
class Student
{
public:
    Student(const std::string& name) : m_name(name)
    {

    }
    ~Student()
    {
        m_name = "";
        m_books.clear();
    }

    void addBook(const std::string& bookName)
    {
        m_books.push_back(bookName);
    }

    void printAllBooks() const
    {
        for (const auto& book : m_books) {
            std::cout << book << "\n";
        }
    }

private:
    std::string m_name;
    std::vector<std::string> m_books {};
};

int main()
{
    Student s("Bhavith");
    s.addBook("Learn C++");
    s.addBook("For the love of physics");
    s.printAllBooks();
    return 0;
}

Now let’s make this as a singleton

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// Student.cpp
class Student
{
public:

    static Student& instance(const std::string& name)
    {
        static Student instance(name);
        return instance;
    }

    void addBook(const std::string& bookName)
    {
        m_books.push_back(bookName);
    }

    void printAllBooks() const
    {
        for (const auto& book : m_books) {
            std::cout << book << "\n";
        }
    }

private:
    Student(const std::string& name) : m_name(name)
    {

    }
    ~Student()
    {
        m_name = "";
        m_books.clear();
    }
    std::string m_name;
    std::vector<std::string> m_books {};
};

int main()
{
    auto& s = Student::instance("Bhavith");
    s.addBook("Learn C++");
    s.addBook("For the love of physics");
    s.printAllBooks();
    return 0;
}

In the above example, we moved the constructor and the desctructor private, So that we removed the access to creation of Student object. In order to create a instance, we created an interace called instance which assist in creating the Student instance or object.

This approach of creating the singleton is thread-safe because, by default static variable declaration is completely thread-safe in c++, especially after in modern-cpp (c++ onwards)

Always go with this approach while making singleton design pattern, which is much more easier, simpler and thread-safe

1
2
3
4
5
static Student& instance(const std::string& name)
{
    static Student instance(name);
    return instance;
}

This way of implementing the singleton design pattern is called Meyers’ singleton design pattern in simple

Spoiler alert: What happen if object is been copied to other object using = operator, then it breaks the singleton design pattern. But how to achieve it is for future post.

This post is licensed under CC BY 4.0 by the author.

pimpl in C++

Pointer to a `const` or a `const` pointer