定义静态成员变量时,未遵循定义顺序?
我知道来自不同翻译单元的静态变量的初始化顺序问题。不过,我的问题是一个翻译单元内,事实上,一个结构内:定义静态成员变量时,未遵循定义顺序?
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
令我惊讶的是,computeAllMDDeltas
被computeAllActions
之前调用等allActions_
不在computeAllMDDeltas
中使用时初始化。有趣的是,即使在computeAllMDDeltas
中使用allActions_
,也不会调用computeAllActions
。
为什么会发生这种情况,在这种情况下建议的方式是什么?
在定义静态成员变量时,定义顺序没有被遵循?
因为标准说初始化是无序:
[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;
}
};
我正确地认为,一旦这些函数的调用被内联,使用这种技术就没有任何开销了? – AlwaysLearning
@AlwaysLearning如果程序使用多线程支持进行编译,则会有一些开销。初始化必须进行同步,以防止多个线程同时调用该函数时可能发生的争用情况。 – user2079303
另外,你是否意味着使用'static const'(即'static'被错误省略?)来防止每次调用相应函数时重新计算这些变量? – AlwaysLearning
其中'computerAllMDDeltas'使用'allActions_'显然不是无关紧要的一点 - 但你还是删除它。请给我们一个[mcve] - 这对你来说有点帮助,但是因为你是有问题的人,这似乎是合理的。 –
您是否确定*'computeAllMDDeltas'正在使用'allActions_'?你能否更新代码来提供一些关于使用的想法。 –
请注意'allActions_'和'mdDeltas_'的定义是**模板**的定义,而不是对象的定义。 'SlidingTile :: allActions_'和'SlidingTile :: mdDeltas_'没有明确的定义。 –