作者:嵌入式开发小杰
链接:https://www.zhihu.com/question/50533404/answer/3037579077
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
在C++11中实现单例模式的方法有很多种,下面介绍几种常见的实现方式。
1. 饿汉式单例
饿汉式单例指在类加载的时候就创建对象,因此可以保证线程安全。此方法简单明了,但如果单例对象很大,可能会影响程序的启动速度。
```c++
class Singleton {
public:
static Singleton& getInstance() {
static Singleton instance;
return instance;
}
private:
Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
};
```
2. 懒汉式单例
懒汉式单例指只有在第一次使用时才创建对象,因此需要考虑线程安全的问题。可以使用加锁的方式来保证线程安全,但会影响程序的性能。也可以使用双重检查锁定的方式来提高性能。
```c++
class Singleton {
public:
static Singleton& getInstance() {
static Singleton* instance = new Singleton();
return *instance;
}
private:
Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
};
```
3. 线程安全的懒汉式单例
在C++11中可以使用`std::call_once`函数来保证线程安全,该函数只会被调用一次。在`getInstance()`函数中,首先检查`instance`是否已经被创建,如果没有,则调用`std::call_once`函数创建对象。该方法可以保证线程安全,同时也能够提高程序的性能。
```c++
class Singleton {
public:
static Singleton& getInstance() {
std::call_once(flag_, &Singleton::init);
return *instance_;
}
private:
Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
static void init() { instance_ = new Singleton(); }
static std::once_flag flag_;
static Singleton* instance_;
};
std::once_flag Singleton::flag_;
Singleton* Singleton::instance_ = nullptr;
```
4. 多线程环境下的单例
在多线程环境下,需要考虑线程安全的问题。可以使用锁或者原子操作来保证线程安全。
```c++
class Singleton {
public:
static Singleton& getInstance() {
Singleton* tmp = instance_.load(std::memory_order_acquire);
if (!tmp) {
std::lock_guard<std::mutex> lock(mutex_);
tmp = instance_.load(std::memory_order_relaxed);
if (!tmp) {
tmp = new Singleton;
instance_.store(tmp, std::memory_order_release);
}
}
return *tmp;
}
private:
Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
static std::atomic<Singleton*> instance_;
static std::mutex mutex_;
};
std::atomic<Singleton*> Singleton::instance_{nullptr};
std::mutex Singleton::mutex_;
```
5. 带析构函数的单例
如果单例对象需要执行析构函数,则需要在程序退出时显式销毁单例对象。可以使用静态变量的析构函数来销毁单例对象。
```c++
class Singleton {
public:
static Singleton& getInstance() {
static Singleton instance;
return instance;
}
~Singleton() { std::cout << "Destroy Singleton" << std::endl; }
private:
Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
};
class SingletonDestructor {
public:
~SingletonDestructor() { Singleton::getInstance(); }
};
SingletonDestructor destructor;
```
以上是C++11中实现单例模式的几种常见方法,具体实现方式可以根据实际需求选择不同的方法。