visual c++ -<class> 在同一类构造函数中初始化静态 std::vector 的问题



如何更正类中声明的静态向量?目前我有一行崩溃,因为向量初始化太晚了。

样本一

#include "stdafx.h"
#include <vector>    
class A{
private:
    int aValue;
public:
    static std::vector<A*> listOfA;
    A(int i)
    {
        aValue = i;
        A::listOfA.push_back(this); // !!! HERE crash in release mode only, in debug mode items add to vector, but remove when vector initialize
    }
};
A testA(1);
std::vector<A*> A::listOfA;

int _tmain(int argc, _TCHAR* argv[])
{
    return 0;
}

样本二

classA.h

#include <vector>
class A{
private:
    int aValue;
public:
    static std::vector<A*> listOfA;
    A(int i);
};

classA.cpp

#include "stdafx.h"
#include "classA.h"
std::vector<A*> A::listOfA;
A::A(int i)
{
  aValue = i;
  A::listOfA.push_back(this); // !!! HERE crash in release mode only, in debug mode items add to vector, but remove when vector initialize
}

main.cpp

#include "stdafx.h"
#include "classA.h"
A testA(1);
int _tmain(int argc, _TCHAR* argv[])
{
    return 0;
}

在示例2中,如果项目中的cpp文件具有以下顺序(编译顺序),则一切正常:classA.cppmain.cpp

如果订购此,我们将崩溃:main.cppclassA.cpp

Statics是按照它们在文件中出现的顺序初始化的,所以当你说:

A testA(1);
std::vector<A*> A::listOfA;

第一个static已初始化,但其构造函数尝试使用第二个static,结果未定义。

如果静态数据在不同的文件中,初始化的顺序是未指定的,所以如果你运气好或不好,它可能会起作用)。一般来说,不要编写依赖于静态初始化顺序的代码。

引用自:http://www.parashift.com/c++-faq-lite/ects.html#faq-10.14这个问题有很多解决方案,但一个非常简单且完全可移植的解决方案是用全局函数listOfA()替换全局对象listOfA,该函数通过引用返回对象。

std::vector<A*>& listOfA()
{
    static std::vector<A*> ans;
    return ans;
}

由于静态本地对象是在第一次控制流经其声明时构造的(仅限),因此上面的新listOfA()语句将只发生一次:第一次调用listOfA。每个后续调用都将返回相同的对象。然后,您所要做的就是将listOfA的用法更改为listOfA():

int _tmain(int argc, _TCHAR* argv[])
{
    // do stuff
    A::listOfA().dostuff();
    // do stuff
}

这被称为首次使用时构造习语,因为它正是这样做的:全局Fred对象是在首次使用时构建的。

这种方法的缺点是对象永远不会被破坏。还有另一种技术可以解决这个问题,但它需要小心使用,因为它会造成另一个(同样严重)问题的可能性。

[编辑]抱歉nbt,没有看到你已经链接到了faq。他值得称赞[/Edit]

最新更新