【问题标题】:C++ Static const initialization order in templates模板中的 C++ 静态 const 初始化顺序
【发布时间】:2020-05-19 09:10:54
【问题描述】:

冒着被标记为重复的风险,我抓住了机会。 考虑以下几点:

给定以下静态 const 数组 arrA 和 arrB,arrB 取决于 arrA。

#include <iostream>
#include <string>
#include <array>

template<int N>
class MyClass {
public:
    static const std::array< int, N> arrA;
    static const std::array< int, N> arrB;
};

template<int N>
std::array<int, N> const MyClass<N>::arrA = []() -> decltype(auto) {
    std::array<int, N> arr;
    for (int i = 0; i < N; i++) {
        arr[i] = 1 + i;
    }
    return arr;
} ();

template<int N>
std::array<int, N> const MyClass<N>::arrB = []() -> decltype(auto) {
    std::array<int, N> arr;
    for (int i = 0; i < N; i++) {
        arr[i] = arrA[i] + 1;
    }
    return arr;
} ();


int main()
{
    constexpr int i = 3;
    std::cout << std::to_string(MyClass<i>::arrB[0]) << std::endl;
}

如果我理解正确,这是标准中给出的静态 const 成员无序初始化的情况:

1) 无序动态初始化,仅适用于未明确专门化的(静态/线程局部)类模板静态数据成员和变量模板(C++14 起)。此类静态变量的初始化相对于所有其他动态初始化的顺序是不确定的,除非程序在变量初始化之前启动线程,在这种情况下,它的初始化是无顺序的 (C++17 起)。相对于所有其他动态初始化,此类线程局部变量的初始化是无序的。

我能找到的最佳答案是here,但没有提及是否存在允许以有序方式执行此类初始化的已知模式。在保持static const 的同时还能做到这一点吗?

理想情况下,我希望数组保持const,否则问题很简单。

虽然这个示例可以使用constexpr 构建,但在实际情况下需要动态初始化(我使用&lt;random&gt;)。

编辑:我觉得有趣的是,无论源中的声明或定义顺序如何,arrB 都会在 arrA 之前初始化。

【问题讨论】:

  • 仍有办法将静态变量包装在函数中(延迟初始化)。

标签: c++ static initialization c++14 constants


【解决方案1】:

如果你想保证初始化的顺序,你必须将两个数组包装在一个结构中,并使用结构的构造函数来初始化静态变量。 Here 就是我的意思的一个例子。

#include <iostream>

template <typename T>
struct A {
    struct B {
        B() : c(0), d(c + 1) {}
        T c;
        T d;
    };
    static B b;

    static T& c() {
        return b.c;
    }

    static T& d() {
        return b.d;
    }
};

template <typename T>
typename A<T>::B A<T>::b{};

int main() {
    std::cout << A<int>::b.c << ", " << A<int>::b.d << std::endl;
    std::cout << A<int>::c() << ", " << A<int>::d() << std::endl;
    return 0;
}

如果您这样做,您可能希望提供访问器,例如示例(c()d()) - 您还可以使用私有结构和访问器结果的常量,因此,例如,你可以这样做

template <typename T>
struct A {
    static const T& c() {
        return b.c;
    }

    static T& d() {
        return b.d;
    }

    private:   
    struct B {
        B() : c(0), d(c + 1) {}
        T c;
        T d;
    };
    static B b;
};

【讨论】:

    猜你喜欢
    • 2012-02-02
    • 1970-01-01
    • 2021-07-12
    • 1970-01-01
    • 2011-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多