在 C++ 中通过调用静态 class 函数初始化的全局静态变量
Global static variable initialised with a call to static class function in c++
不确定问题的表述是否正确,但这就是问题所在。
我有一个静态库,其中 class 在 a.h 中:
#pragma once
#include <vector>
class A{
public:
void Run() {
data_.push_back(10);
std::cout << "size: " << data_.size() << std::endl;
}
private:
static std::vector<int> data_;
};
a.cpp如下:
#include "a.h"
std::vector<int> A::data_;
我在 b.h 中还有一个 class:
#pragma once
#include <string>
class B
{
public:
static std::string Get();
};
和b.cpp:
#include "b.h"
#include "a.h"
std::string B::Get()
{
static A a;
a.Run();
return "foo";
}
现在使用上述静态库的我的主要应用程序如下:
#include <iostream>
#include "a.h"
#include "b.h"
static std::string var1= B::Get();
int main(int argc, char** argv)
{
A a;
a.Run();
}
试图理解为什么输出是:
尺寸:1
尺寸:1
整个 class 的每个静态数据成员应该有一个实例,因此应该有一个对 A::data_ 构造函数的调用。
我在打 "static initialization order fiasco" 吗? IE。 data_ 在我使用之前没有初始化,但我应该会崩溃?
现在让我们想象一下我的 data_ 包含动态初始化的项目(none POD)。如果最后 data_ 包含一项,尽管我插入了 2 项,它将如何被破坏?
这就是我真实代码中实际发生的情况(它有时会在数据销毁期间崩溃)。
去掉global static ( static std::string var1= B::Get(); )解决了问题,但还是想了解下引擎盖问题。
描述的案例可以在 VS2015 中重现(真实案例可以在 gcc 6.2 中重现)
Am I hitting "static initialization order fiasco"?
很有可能。
您可以通过函数调用使 class 的 static
数据可用,从而解决此问题。例如
class A{
public:
void Run() {
getData().push_back(10);
std::cout << "size: " << getData().size() << std::endl;
}
private:
static std::vector<int>& getData();
};
std::vector<int>& A::getData()
{
static std::vector<int> data;
return data;
}
当您这样做时,data
将在第一次调用 A::getData()
时被初始化。它完全消除了静态初始化顺序问题。
不确定问题的表述是否正确,但这就是问题所在。
我有一个静态库,其中 class 在 a.h 中:
#pragma once
#include <vector>
class A{
public:
void Run() {
data_.push_back(10);
std::cout << "size: " << data_.size() << std::endl;
}
private:
static std::vector<int> data_;
};
a.cpp如下:
#include "a.h"
std::vector<int> A::data_;
我在 b.h 中还有一个 class:
#pragma once
#include <string>
class B
{
public:
static std::string Get();
};
和b.cpp:
#include "b.h"
#include "a.h"
std::string B::Get()
{
static A a;
a.Run();
return "foo";
}
现在使用上述静态库的我的主要应用程序如下:
#include <iostream>
#include "a.h"
#include "b.h"
static std::string var1= B::Get();
int main(int argc, char** argv)
{
A a;
a.Run();
}
试图理解为什么输出是:
尺寸:1
尺寸:1
整个 class 的每个静态数据成员应该有一个实例,因此应该有一个对 A::data_ 构造函数的调用。 我在打 "static initialization order fiasco" 吗? IE。 data_ 在我使用之前没有初始化,但我应该会崩溃?
现在让我们想象一下我的 data_ 包含动态初始化的项目(none POD)。如果最后 data_ 包含一项,尽管我插入了 2 项,它将如何被破坏?
这就是我真实代码中实际发生的情况(它有时会在数据销毁期间崩溃)。
去掉global static ( static std::string var1= B::Get(); )解决了问题,但还是想了解下引擎盖问题。
描述的案例可以在 VS2015 中重现(真实案例可以在 gcc 6.2 中重现)
Am I hitting "static initialization order fiasco"?
很有可能。
您可以通过函数调用使 class 的 static
数据可用,从而解决此问题。例如
class A{
public:
void Run() {
getData().push_back(10);
std::cout << "size: " << getData().size() << std::endl;
}
private:
static std::vector<int>& getData();
};
std::vector<int>& A::getData()
{
static std::vector<int> data;
return data;
}
当您这样做时,data
将在第一次调用 A::getData()
时被初始化。它完全消除了静态初始化顺序问题。