C++单例模式,为什么这段只会执行一次构造函数

为什么这段代码只会执行一次构造函数 第二次和第三次会跳过构造函数

是否与函数是static和对象的类型是static有关?

singleton.h

#ifndef SINGLETON_H_
#define SINGLETON_H_

class Singleton
{
public:
    static Singleton * GetTheOnlyInstance();
protected:
    Singleton(){}
private:
    ...
};

#endif
singleton.cpp

#include "singleton.h"

Singleton * Singleton::GetTheOnlyInstance()
{
    static Singleton objSingleton;
    return &objSingleton;
}
调用程序 main.cpp

#include <iostream>
#include "singleton.h"

using namespace std;

int main()
{
    Singleton * ps1 = Singleton::GetTheOnlyInstance();
    Singleton * ps2 = Singleton::GetTheOnlyInstance();
    Singleton * ps3 = Singleton::GetTheOnlyInstance();
    
    cout << ps1 << endl << ps2 << endl << ps3 << endl;

    return 0;
}
输出结果
0x6013b0
0x6013b0
0x6013b0
证明ps1、ps2、ps3是同一个地址 即同一个对象
阅读 4.9k
3 个回答

这里用到了static关键字的两个方面:

  1. 在类中是static成员函数:一个需要访问类成员,而不需要针对特定对象去调用的函数,也被称为一个static成员函数。
  2. 对于局部static变量定义: 如果某个局部变量被声明为static,那怎么只会在第一次执行到该变量时定义初始化该变量,之后的调用会一直使用该静态分配对象,所以实现了单例模式

为什么static的局部变量只执行一次,起风了说的第二点就是.

我想补充一下. 对于单例模式的实现, 如果连同线程安全问题考虑还是挺复杂的. 每个类都实现一遍就是copy来copy去. 因此, 可用的c++实例一般都泛化以支持不同的类, 并且支持多个入参.
对于第一个需求类模板可以实现, c++11引入了可变参数模板可以满足第二个需求. 具体实现如下:

 template<typename T>
 class SingleClass
 {
 private:
     static T* pInstance_;
 
 public:
     template<typename... Args>
     static T *InitInstance(Args&&... args) {
         if(nullptr == pInstance_) {
             pInstance_ = new T(std::forward<Args>(args)...) ;
         }
         return pInstance_;
     }   
 
     static T *getInstance() {
         if(pInstance_ == nullptr) {
             throw;
         }
         return pInstance_;
     }   
 
     static void destroyInstance() {
         delete pInstance_; 
         pInstance_ = nullptr;
     }   
 };
 template<typename T> T * SingleClass<T>::pInstance_ = nullptr;
 
 struct TestA
 {
 private:
     friend class SingleClass<TestA>;
     TestA(int x) {
         std::cout<<"this is num:" <<x<<std::endl;
     }   
 };

 
不过要考虑多线程安全/安全销毁等诉求,还是有更多的东西需要考量, 参考下面两个高阶实现:
http://www.cnblogs.com/loveis...
https://github.com/chenshuo/m...

类的静态字段以及全局变量在main之前初始化,并且只初始化一次。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题