目录
C++的变量初始化顺序时有先后的,比如下面的例子中的n1,n2
通过static对象替换non-static对象来规避初始化顺序问题
-
C++的变量初始化顺序时有先后的,比如下面的例子中的n1,n2
#include <iostream> using namespace std; class A { public: A() :n2(0), n1(n2 + 2) {} void print() { cout << "n1:" << n1 << " , n2:" << n2 << endl; } private: int n1; int n2; }; int main() { A a; a.print(); return 0; }
打印结果:
n1:32769 , n2:0 // 不是预期的n2 = 0, n1 = 2。
- 这里就引出来一个问题:C++类成员变量初始化顺序是怎么样的呢?
参考:C++类中变量的初始化顺序_zion--6135的博客-优快云博客
- 解决办法:(1)保证使用变量前手动初始化。(2)类中的变量B用变量A初始化,注意A,B的声明顺序。
-
不同编译单元的non static对象初始化顺序是不确定的
- 不同编译单元之间的non-local static 对象的初始化顺序是不确定的。比如:
// main.cpp
#include <iostream> #include "test.h" using namespace std; class A { public: A(); private: int n1; int n2; }; A::A() : n1(2), n2(3) { bb.print(); } int main() { A a; return 0; }
//test.h
#include "iostream" class B { public: B():n3(2),n4(3){ } void print() { std::cout << "n3:" << n3 << " , n4:" << n4 << std::endl; } private: int n3; int n4; }; extern B bb;
然后编译:
g++ main.cpp test.h
- 编译没有通过:如下报错----
/usr/bin/ld: /tmp/ccOu0q7v.o: in function `A::A()':
main.cpp:(.text+0x28): undefined reference to `bb'
collect2: error: ld returned 1 exit status
- 这正是问题所在:不同编译单元之间的non-local static 对象的初始化顺序是不确定的。所以在上述例子中:想要保证在A构造函数中用 B bb这个变量,就需要保证B bb的构造函数先于A的构造函数。
-
通过static对象替换non-static对象来规避初始化顺序问题
通过单例模式来规避。不同编译单元的初始化顺序问题。
于是上述的test.h和main.cpp应该做如下修改
//main.cpp A::A() : n1(2), n2(3) { B::instance()->print(); //调用 }
class B { ... static B* instance() { static B* bb = new B; return bb; } ... }
编译可通过,也过了编译。
- 本质上的原因是,static成员函数是独立于类而存在的,不受是否有具体的类对象的影响,或者说static 成员函数先于不同编译单元的non static对象的初始化。