2016-01-19 90 views
4

是什么区别:C++ 11中的静态局部变量?

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之间单身人士的生活有什么不同?对象的内存位置?任何差异一般?

回答

8

这两种情况下物体的寿命是不同的。 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分配的任何内容都将存储在堆中。

+0

作为一种事后,也有可能是在程序行为时A''或'B'过大而差异分别适合堆或数据段。如果'B'太大,那么'new B'应该抛出'std :: bad_alloc'。在'A'的情况下,我不确定是否抛出可捕获的异常,或者程序是否会发生seg-fault和死亡。 – paddy

0

添加到第一个答案,2条评论(假设你想创建一个单身人士)。

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

编辑:下面是一个SO问题,其中包含答案相关的裁判标准:Heap/dynamic vs. static memory allocation for C++ singleton class instance

+0

正如问题中所提到的,在C++ 11中:(1)和(2)都是由编译器保证的。 (1)编译器保证* static *局部变量初始化是线程安全的。 (2)编译器保证* static *局部变量初始化只会被执行一次,所有后续调用该函数将跳过静态局部变量的重新初始化(因此每次都不会创建新的实例)。 – iBrAaAa

+0

@iBrAaAa?这个问题没有提到标准的任何保证。相关部分是6.7.4,参见例如。 HTTP://计算器。com/questions/15062767/heap-dynamic-vs-static-memory-allocation-for-c-singleton-class-instance因此,使用函数静态变量意味着你可以通过同步的标准获得帮助。 –