---
# System prepended metadata

title: C++ Singleton
tags: [c++, ' tutorial', ' singleton']

---

---
tags: c++, singleton, tutorial,
lintConfig:
  MD013: false
---

# C++ Singleton

## What is singleton

Singleton是整個類別(class)只會有一個實例(instance)存在，有利於系統控制整體的行為。

According to [wiki](https://en.wikipedia.org/wiki/Singleton_pattern):

> The singleton design pattern solves problems by allowing it to:
>
> - Ensure that a class only has one instance
> - Easily access the sole instance of a class
> - Control its instantiation
> - Restrict the number of instances
> - Access a global variable
>
> The singleton design pattern describes how to solve such problems:
>
> - Hide the constructors of the class.
> - Define a public static operation (getInstance()) that returns the sole instance of the class.
>

## Eager singleton & lazy singleton

### Eager singleton

Eager版本會在main前，class被定義時就初始化完成，因為static member variable會被使為全域變數。而缺點為會在main開始執行之前初始化此class，萬一class初始資源龐大時間久，則會影響到main開始的執行時間。

```cpp=
#include <iostream>

using namespace std;

class EagerSingleton {
public:
  static EagerSingleton &getInstance() {
    return gInstance;
  }

  // copy contructor
  EagerSingleton(const EagerSingleton &) = delete;
  // assignment operator
  EagerSingleton &operator=(const EagerSingleton &) = delete;

private:
  static EagerSingleton gInstance;

  EagerSingleton() { cout << "EagerSingleton contructor called!\n"; }
  ~EagerSingleton() { cout << "EagerSingleton destructor called!\n"; }
};

/* class definition */
EagerSingleton EagerSingleton::gInstance;

/* main function */
int main(void) {
  cout << "Main started!\n";
  cout << "getInstance()    addr: " << &EagerSingleton::getInstance() << '\n';
  EagerSingleton& s = EagerSingleton::getInstance();
  cout << "reference object addr: " << &s << '\n';
  return 0;
}
```

public中用`getInstane` 回傳`gInstance`的reference。將copy constructor和assignment operator失去作用以免不小心複製instance。`gInstance` 為一個private的static member。而contructor以及destructor放在private中即不可用宣告建立此物件。


在 main 中呼叫 `getInstance`. 最終output:

```bash=
$ ./eager_singleton                             
EagerSingleton contructor called!
Main started!
getInstance()    addr: 0x5607a00a4191
reference object addr: 0x5607a00a4191
EagerSingleton destructor called!
```

可以看到在 main 開始執行前，class 已被初始化。並且在main結束時 destructor 會被呼叫。

### Lazy singleton

Lazy singleton 在被用到時才會初始化，

```cpp=
#include <iostream>

using namespace std;

class LazySingleton {
public:
  static LazySingleton* getInstance() {
    cout << "Get LazySingleton instance\n";
    if (gInstance == nullptr) {
      gInstance = new LazySingleton();
    }
    return gInstance;
  }

  // copy contructor
  LazySingleton(const LazySingleton &) = delete;
  // assignment operator
  LazySingleton &operator=(const LazySingleton &) = delete;

private:
  static LazySingleton *gInstance;

  LazySingleton() { cout << "LazySingleton contructor called!\n"; }
  ~LazySingleton() { cout << "LazySingleton destructor called!\n"; }
};

/* class definition */
LazySingleton *LazySingleton::gInstance = nullptr;

/* main function */
int main(void) {
  cout << "Main started!\n";
  cout << "getInstance()    addr: " << LazySingleton::getInstance() << '\n';
  LazySingleton* s = LazySingleton::getInstance();
  cout << "reference object addr: " << s << '\n';
  return 0;
}
```

```bash=
$ ./lazy_singleton
Main started!
getInstance()    addr: LazySingleton contructor called!
0x5629aced42c0
reference object addr: 0x5629aced42c0
```

```cpp=
#include <iostream>

using namespace std;

class LazySingleton {
public:
  static LazySingleton& getInstance() {
    cout << "Get LazySingleton instance\n";
    if (gInstance == nullptr) {
      gInstance = new LazySingleton();
    }
    return *gInstance;
  }

  // copy contructor
  LazySingleton(const LazySingleton &) = delete;
  // assignment operator
  LazySingleton &operator=(const LazySingleton &) = delete;

private:
  static LazySingleton *gInstance;

  LazySingleton() { cout << "LazySingleton contructor called!\n"; }
  ~LazySingleton() { cout << "LazySingleton destructor called!\n"; }
};

/* class definition */
LazySingleton *LazySingleton::gInstance = nullptr;

/* main function */
int main(void) {
  cout << "Main started!\n";
  cout << "getInstance()    addr: " << &LazySingleton::getInstance() << '\n';
  LazySingleton& s = LazySingleton::getInstance();
  cout << "reference object addr: " << &s << '\n';
  return 0;
}
```
