定义静态成员变量时,未遵循定义顺序?

问题描述:

我知道来自不同翻译单元的静态变量的初始化顺序问题。不过,我的问题是一个翻译单元内,事实上,一个结构内:定义静态成员变量时,未遵循定义顺序?

template <int size> 
struct SlidingTile { 
    using AllActions = std::array<int, size>; 
    using AllMDDeltas = std::array<int, size>; 

    int mdDelta(int i) const { 
     return mdDeltas_[i]; 
    } 

    static AllActions computeAllActions() { 
     std::cout << "computeAllActions" << std::endl; 
     AllActions res; 
     for (int i = 0; i < size; ++i) res[i] = i; 
     return res; 
    } 

    static AllMDDeltas computeAllMDDeltas() { 
     std::cout << "Entered computeAllMDDeltas" << std::endl; 
     AllActions res; 
     for (int i = 0; i < size; ++i) res[i] = 10 * allActions_[i]; 
     std::cout << "Exiting computeAllMDDeltas" << std::endl; 
     return res; 
    } 

private: 
    static const AllActions allActions_; 
    static const AllMDDeltas mdDeltas_; 
}; 

template <int size> 
const typename SlidingTile<size>::AllActions 
    SlidingTile<size>::allActions_ = SlidingTile<size>::computeAllActions(); 

template <int size> 
const typename SlidingTile<size>::AllMDDeltas 
    SlidingTile<size>::mdDeltas_ = SlidingTile<size>::computeAllMDDeltas(); 

int main() { 
    SlidingTile<3> s; 
    std::cout << s.mdDelta(2) << std::endl; 
    return 0; 
} 

输出是:

Entered computeAllMDDeltas 
Exiting computeAllMDDeltas 
computeAllActions 

令我惊讶的是,computeAllMDDeltascomputeAllActions之前调用等allActions_不在computeAllMDDeltas中使用时初始化。有趣的是,即使在computeAllMDDeltas中使用allActions_,也不会调用computeAllActions

为什么会发生这种情况,在这种情况下建议的方式是什么?

+1

其中'computerAllMDDeltas'使用'allActions_'显然不是无关紧要的一点 - 但你还是删除它。请给我们一个[mcve] - 这对你来说有点帮助,但是因为你是有问题的人,这似乎是合理的。 –

+0

您是否确定*'computeAllMDDeltas'正在使用'allActions_'?你能否更新代码来提供一些关于使用的想法。 –

+2

请注意'allActions_'和'mdDeltas_'的定义是**模板**的定义,而不是对象的定义。 'SlidingTile :: allActions_'和'SlidingTile :: mdDeltas_'没有明确的定义。 –

在定义静态成员变量时,定义顺序没有被遵循?

因为标准说初始化是无序:

[basic.start.init/2(N4140标准草案)

...明确专门的模板类静态的定义数据成员已经命令初始化。其他 类模板静态数据成员(即,隐含或显式实例化的专业化)具有无序 初始化。 ...


什么是在这种情况下,建议的方式?

同跨翻译单元初始化:构建在第一次使用成语:

struct SlidingTile { 
    // ... 
private: 
    static const AllActions& allActions() { 
     static const AllActions instance = computeAllActions(); 
     return instance; 
    } 
    static const AllMDDeltas& mdDeltas() { 
     static const AllMDDeltas instance = computeAllMDDeltas(); 
     return instance; 
    } 
}; 
+0

我正确地认为,一旦这些函数的调用被内联,使用这种技术就没有任何开销了? – AlwaysLearning

+0

@AlwaysLearning如果程序使用多线程支持进行编译,则会有一些开销。初始化必须进行同步,以防止多个线程同时调用该函数时可能发生的争用情况。 – user2079303

+0

另外,你是否意味着使用'static const'(即'static'被错误省略?)来防止每次调用相应函数时重新计算这些变量? – AlwaysLearning