通过调用 C++ 中的静态类函数初始化全局静态变量
Posted
技术标签:
【中文标题】通过调用 C++ 中的静态类函数初始化全局静态变量【英文标题】:Global static variable initialised with a call to static class function in c++ 【发布时间】:2017-04-02 16:46:22 【问题描述】:不确定问题的表述是否正确,但问题就在这里。
我有一个静态库,其中我在 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 有另一门课:
#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
整个类的每个静态数据成员都应该有一个实例,因此应该只调用一次 A::data_ 构造函数。 我在打"static initialization order fiasco"吗? IE。 data_ 在我使用它之前没有初始化,但是我应该会崩溃吗?
现在让我们想象一下我的 data_ 包含动态初始化的项目(没有 POD)。如果最后 data_ 包含一个项目,它将如何被破坏,尽管我已经插入了 2?
这就是我现实生活中的代码中实际发生的情况(它有时会在破坏数据时崩溃_)。
摆脱全局静态( static std::string var1= B::Get(); )解决了问题,但我仍然想了解引擎盖下的问题。
所描述的案例可以在 VS2015 中重现(真实案例在 gcc 6.2 中可以重现)
【问题讨论】:
【参考方案1】:我是不是遇到了“静态初始化顺序惨败”?
很有可能。
您可以通过函数调用使类的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()
时被初始化。它完全消除了静态初始化顺序问题。
【讨论】:
@R Sahu,是的,您的建议确实解决了这个问题。尽管还有一个更重要的细节:如果在类的析构函数中需要调用任何静态函数,请确保在构造函数中进行相同的调用,否则它可能已经被析构了。 @Tadzys,我不记得在函数内部构造和销毁static
对象是一个问题,如果您遇到任何问题,请在另一个帖子中详细说明。跨度>
@R Sahu,可以说我的 getData 持有静态 std::vectorstd::vector<std::vector<int>>
。
@R Sahu,可以说 getData 持有静态 std::vector以上是关于通过调用 C++ 中的静态类函数初始化全局静态变量的主要内容,如果未能解决你的问题,请参考以下文章