gpt4 book ai didi

c++ - 在模板中初始化静态成员

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:37:25 24 4
gpt4 key购买 nike

这是一个最小的例子:

#include <iostream>

struct B {
B() { x = 42; }
static int x;
};

int B::x;

template <int N>
struct A {
int foo() { return b.x; }
static B b;
};

template<int N>
B A<N>::b;

//template struct A<2>; // explicit instantiation with N = 2 (!)

int main(int argc, char **argv) {
std::cout << A<1>().foo() << std::endl;
return 0;
}

此程序使用 g++ 4.9.2 写入 42,但使用 Visual Studio 2015 RC 写入 0。另外,如果我取消显式实例化的注释,VS2015RC 也会给出 42,这很有趣,因为这里的模板参数与 main 函数中使用的不同。

这是一个错误吗?我假设 g++ 是正确的,因为 foo 中有对 b 的引用,所以应该调用 B 的构造函数。


编辑:有一个简单的解决方法 - 如果 B 中有一个非静态变量,它在 A 中被引用,VS2015RC 将正确编译:

// ...

struct B {
B() { x = 42; }
static int x;
int y; // <- non-static variable
};

// ...

template <int N>
struct A {
int foo() { b.y; return b.x; } // <- reference to b.y
static B b;
};

这似乎可行,尽管 b.y 作为声明显然是 NOP。

最佳答案

来自 [basic.start.init]:

Variables with static storage duration (3.7.1) or thread storage duration (3.7.2) shall be zero-initialized (8.5) before any other initialization takes place. A constant initializer for an object o is an expression that is a constant expression, except that it may also invoke constexpr constructors for o and its subobjects even if those objects are of non-literal class types. [ ... ]

Together, zero-initialization and constant initialization are called static initialization; all other initialization is dynamic initialization. Static initialization shall be performed before any dynamic initialization takes place.

在我们的例子中,b静态初始化但 b.x是动态初始化的(构造函数不是 constexpr)。但我们也有:

It is implementation-defined whether the dynamic initialization of a non-local variable with static storage duration is done before the first statement of main. If the initialization is deferred to some point in time after the first statement of main, it shall occur before the first odr-use (3.2) of any function or variable defined in the same translation unit as the variable to be initialized.

Odr-used 手段,来自 [basic.def.odr]:

A variable x whose name appears as a potentially-evaluated expression ex is odr-used by ex unless applying the lvalue-to-rvalue conversion (4.1) to x yields a constant expression (5.20) that does not invoke any nontrivial functions and, if [ ... ]

但评估b.x不会产生常量表达式,所以我们可以到此为止 - b.x A<N>::foo() odr-used ,这也是第一个 odr-use。因此,虽然初始化不必在 main() 之前发生, 它必须在 foo() 之前发生.所以如果你得到 0,那就是编译器错误。

关于c++ - 在模板中初始化静态成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31383759/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com