跨越不同翻译单元的c ++变量/实例初始化顺序

时间:2015-11-15 11:47:11

标签: c++ design-patterns initialization singleton translation-unit

提前致谢。

我在一些真实的项目中看到了这些代码。我只是简化了它们来表达我的问题。基类将 this 指针放入其构造函数中的向量(vec)。使用这个技巧,我们可以利用动态绑定来调用派生类'外部方法(在主要功能中)。关键是将向量定义放在Bash.h中,并在main.cpp中声明。

我的问题是,输出不是我想要的。为什么vec被初始化并在一个翻译单元中使用( base.c ,我们可以看到大小为1),然后在其他翻译单元( main.c ,我们可以看到大小变为0),是初始化并再次清除?我想知道不同翻译单位的初始化顺序。似乎Derive :: dInstance是第一个,那么vec是第二个,但为什么呢?

  

Base.h

#ifndef BASE_H
#define BASE_h

#include<iostream>
#include<vector>
using namespace std;
class Base{
    public:
        Base();
        virtual void speak();
};

#endif
  

Base.cpp

#include"Base.h"

vector<Base*> vec;
Base::Base() {
    vec.push_back(this);
    cout << "Base's constructor" << endl;
    cout << "Base() vector size: " << vec.size() << endl;**
}

void Base::speak() {
    cout << "I am Base" << endl;
}
  

Derive.h

#ifndef DERIVE_H
#define DERIVE_h
#include<iostream>
#include"Base.h"

class Derive: public Base {
    public:
        Derive();
        virtual void speak();

        static Derive dInstance;
};
#endif
  

Derive.cpp

#include "Derive.h"

// static member definition
Derive Derive::dInstance;

Derive::Derive() {
    cout << "Derived's construtor" << endl;**
}
void Derive::speak() {
    cout << "I am Derived" << endl;
}
  

的main.cpp

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

using namespace std;

extern vector<Base*> vec;
int main(int argc, char *argv[]) {
    cout << "vector size: " << vec.size() << endl;

    for(vector<Base*>::iterator iter = vec.begin(); iter != vec.begin(); iter++) {
        (*iter)->speak();
    }
}

输出:

Base's constructor
Base() vector size: 1
Derived's constructor
main() vector size: 0

2 个答案:

答案 0 :(得分:1)

这是static initialization order fiasco”

未定义staticDerived.cpp(或全局)变量之间的初始化顺序。因此,考虑如果在Base.cpp之前初始化foo文件会发生什么,然后添加到未初始化(构造)的向量,导致未定义的行为然后初始化矢量。

答案 1 :(得分:-1)

首先,初始化顺序没有规定不同的翻译单位。

并且,全局变量和全局静态变量将在main函数之前初始化。属于函数FuncA()的局部静态变量将在第一次调用FuncA()时初始化。