How come the definition order is not followed when defining static member variables?

雨燕双飞 提交于 2019-12-10 15:11:44

问题


I know about the problem of the order of initialization of static variables from different translation units. However, my problem is within one translation unit and, in fact, within one struct:

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;
}

The output is:

Entered computeAllMDDeltas
Exiting computeAllMDDeltas
computeAllActions

To my surprise, computeAllMDDeltas gets called before computeAllActions and so allActions_ is not initialized when it is used in computeAllMDDeltas. Interestingly, computeAllActions is not called even when allActions_ is used in computeAllMDDeltas.

Why does this happen and what is the advised way in this situation?


回答1:


How come the definition order is not followed when defining static member variables?

Because the standard says that the initialization is unordered:

[basic.start.init] /2 (N4140 standard draft)

... Definitions of explicitly specialized class template static data members have ordered initialization. Other class template static data members (i.e., implicitly or explicitly instantiated specializations) have unordered initialization. ...


what is the advised way in this situation?

Same as initialization across translation units: Construct On First Use idiom:

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;
    }
};


来源:https://stackoverflow.com/questions/42206540/how-come-the-definition-order-is-not-followed-when-defining-static-member-variab

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!