c++ - 静态内联成员初始化顺序

标签 c++ c++17 static-initialization

C++ 中一个众所周知的问题是 static initialization order fiasco .当使用 C++17 静态内联成员时,它仍然被认为是一个问题吗?

这里是一个静态内联成员在两个不同的翻译单元(a.cpp 和 b.cpp)中用作两个非内联静态成员的初始值设定项的示例:

counter.hh

#pragma once

#include <vector>
#include <fstream>

class Counter
{
    public:
        Counter()  { std::ofstream os("o.txt", std::ofstream::app); os << "Counter created" << std::endl; }
        ~Counter() { std::ofstream os("o.txt", std::ofstream::app); os << "Counter destroyed" << std::endl; }
        void add_instance()    
        { 
            ++m_instances; 
            std::ofstream os("o.txt", std::ofstream::app); os << "Counter increased: " << m_instances << std::endl; 
        }
        void remove_instance() 
        { 
            --m_instances; 
            std::ofstream os("o.txt", std::ofstream::app); os << "Counter decreased: " << m_instances << std::endl; 
        }

    private:
        int m_instances = 0;
};

class Object
{
    public:
        Object(Counter & counter) : m_counter(counter) 
        {
            m_counter.add_instance(); 
            std::ofstream os("o.txt", std::ofstream::app); os << "Object created" << std::endl; 
        }
        ~Object() 
        { 
            m_counter.remove_instance(); 
            std::ofstream os("o.txt", std::ofstream::app); os << "Object destroyed" << std::endl; 
        }

    private:
        Counter & m_counter;
};

struct C
{
    static inline Counter static_counter{};
};

a.hh

#pragma once

#include "counter.hh"

struct A
{
    static Object static_a; //not inline
};

a.cpp

#include "a.hh"

Object A::static_a{C::static_counter};

b.hh

#pragma once

#include "counter.hh"

struct B
{
    static Object static_b; //not inline
};

b.cpp

#include "b.hh"

Object B::static_b{C::static_counter};

main.cpp

#include "a.hh"
#include "b.hh"

int main() { }

输出(使用 MSVC 16.1.2)

Counter created
Counter increased: 1
Object created
Counter increased: 2
Object created
Counter decreased: 1
Object destroyed
Counter decreased: 0
Object destroyed
Counter destroyed

我认为,就初始化而言,这种做法是安全的,因为 C++17 标准确保静态内联成员:(1) 始终在任何使用前初始化,以及 (2) 在多个翻译单元中仅初始化一次.

但我想知道此模式是否存在任何隐藏的缺点,例如与不同 TU 中每个变量的销毁顺序有关。 static_astatic_b 总是在 static_counter 之前销毁是否明确定义?

最佳答案

是的,这很好,因为在每个翻译单元中 static_counter 都是 defined before static_a/static_b。不能保证销毁顺序是相反的(给定线程,无论如何这是没有意义的),但是 reverse of each guarantee holds , 所以这也有效。

关于c++ - 静态内联成员初始化顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56515342/

相关文章:

c++ - 不匹配调用 '...' 模板 C++,OOP

c++ - 与 C 字符串 `std::string` + (`malloc` 相比, `memcpy` 的性能真的很差)

c++ - 如何使用 Daffodil 将旧的 VC6 项目迁移到 VS2010

c++ - 如何编写一个错误结构,它可以包含不同的强类型枚举作为错误代码?

C++ unique_ptr 从派生到基础的转换

从另外两个数组创建一个静态分配的数组

c++ - 类层次结构中的静态初始化顺序

c++ - Nemiver 仅显示 ASM 代码

c++ - 函数模板实例的地址可以作为函数指针传递给某个函数吗?

java - 为什么静态初始化程序允许在 Java 中重新初始化静态变量?