C++11 中的静态局部变量

Static local variable in C++11?

本文关键字:局部变量 静态 C++11      更新时间:2023-10-16

两者之间有什么区别:

class A {
 public:
   static const A& GetInstance() {
     static A a;
     return a;
   }
};

class B {
  public:
   static const B* GetInstance() {
     static B* b = new B;
     return b;
   }
};

?A 和 B 之间的单例寿命是否有区别?对象的内存位置?一般有什么区别吗?

在这两种情况下,对象的生存期是不同的。 C++保证静态局部对象将以与其构造相反的顺序销毁。 在这两种情况下,构造都将在首次调用GetInstance时发生。

但是,在第二种情况下,变量b被分配了一个分配有 new 的指针。 从静态存储中删除b时,该内存将保留,直到堆最终被拆除。 在该阶段,它将被视为"泄漏",并且永远不会调用B的析构函数(如果有)。

最好像这样实现基于指针的方法:

class B {
  public:
   static const B* GetInstance() {
     static std::unique_ptr<B> b( new B );
     return b.get();
   }
};

现在,将调用B::~B()(如果适用),并且在销毁内存时将正确删除该内存b并且生存期与第一个示例相同。

这只留下了您关于内存位置的问题。 位置会有所不同。 静态变量通常存储在程序的数据段中,而分配new的任何变量都将存储在堆中。

在第一个答案中添加 2 条注释(假设您要创建一个单例)。

  1. 如果 2 个线程尝试访问静态实例重叠,如果访问是第一次访问(运行构造函数时),则存在线程/争用问题。如今,C++具有编译器/标准支持,可自动使此静态单例初始化线程安全。
  2. 在堆情况下,您不希望每次都在堆上创建新实例。只需检查 nullptr,并且仅在第一次在堆上创建实例。

编辑:这是一个SO问题,其中答案包含与标准相关的参考:C++单例类实例的堆/动态与静态内存分配