在同一个类构造函数</class>中初始化static std :: vector <class>时出现问题

时间:2011-05-28 06:37:07

标签: class visual-c++ vector crash initialization

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

示例

#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.cpp main.cpp中

如果订购此产品,我们会崩溃: main.cpp中 classA.cpp

2 个答案:

答案 0 :(得分:0)

静态按照它们出现在文件中的顺序进行初始化,所以当你说:

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

初始化第一个静态,但是它的构造函数尝试使用第二个静态结果,但结果不确定。

如果静态文件位于不同的文件中,则初始化顺序未指定,因此如果您幸运或不幸,它可能会起作用。通常,不要编写依赖于静态初始化顺序的代码。

答案 1 :(得分:0)

引自:http://www.parashift.com/c++-faq-lite/ctors.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,没看到你已经链接到常见问题解答。他值得信任[/编辑]