C++ &引用;静态常数int“;导致链接错误(未定义的引用)

C++ &引用;静态常数int“;导致链接错误(未定义的引用),c++,gcc,static,constants,stdvector,C++,Gcc,Static,Constants,Stdvector,使用以下代码时,链接器错误使我感到困惑: // static_const.cpp -- complete code #include <vector> struct Elem { static const int value = 0; }; int main(int argc, char *argv[]) { std::vector<Elem> v(1); std::vector<Elem>::iterator it; i

使用以下代码时,链接器错误使我感到困惑:

// static_const.cpp -- complete code
#include <vector>

struct Elem {
    static const int value = 0;
};

int main(int argc, char *argv[]) {
    std::vector<Elem> v(1);
    std::vector<Elem>::iterator it;

    it = v.begin();
    return it->value;
}
顺便说一句,这可以用-O1或更好的方式编译;但对于更复杂的情况,它仍然失败。我使用的是gcc版本4.4.4 20100726(Red Hat 4.4.4-13)


你知道我的代码有什么问题吗?

如果你想在结构内部初始化它,你也可以这样做:

struct Elem {
    static const int value = 0;
};

const int Elem::value;
试着把它写成

struct Elem {
    static const int value;
};

const int Elem::value = 0;

etc

我不记得这与
const
静态整数成员的内联初始化是如何相互作用的。

为什么不这样做呢

return Elem::value;

但答案是您正在声明中赋值。这应该适用于基本类型,例如
int
,并且只适用于复杂类型(即类,例如如果您使用的是字符串而不是int)。我在实践中发现,这取决于您使用的编译器的版本。并且,正如您所发现的,是哪种优化级别。

另请参见:本质上,问题在于编译器最终以某种方式扩展了代码,以获取Elem::value的地址。

在大多数编译器中,在类
中定义静态常量可以正常工作。但有些编译器,如Android NDK,如类内定义,会导致链接器错误。对于这种情况,我们可以使用类型化的
enum
s:

struct X
{
  enum : int64_t { VALUE = 100; }; // == static const int64_t VALUE = 100;
};

请看,对于声明具有初始值设定项的情况,没有特殊规则——根据标准,如果声明的对象可能被使用,则必须在某个地方定义它。在实践中,大多数编译器在这方面都有缺陷,如果缺少定义,它们只会为某些用途生成错误,而不会为其他用途生成错误。但是,这并不能解决初始化问题。此外,命中或未命中通常意味着未定义的行为。这只是为了避免他问的问题。事实上,我回答了。我说他所做的应该是有效的(也就是说,没有错),但实际上并不总是有效的。他似乎发现了其中一个“不起作用”的案例。不,“不起作用”是一般情况。
值实际上应该在某个地方定义,而不仅仅是声明。如果您只是将该值用作编译时常量,它通常“无论如何都能工作”。感谢您提供有用的链接,这可能是重复的!它还显示了另一种解决方案,
struct Elem{enum{value=0};}
,它看起来非常吸引人。这可能是很酷的重复!它起作用了。如果可以(知道当时的值),不在结构(类)中初始化它是没有意义的,因为否则所有可能的优化都将丢失。(即,直接传递0,而不是从某个内存地址加载0。)如果这真的是常量,则有“枚举黑客”的替代方法,请参阅:这里也描述了问题:在c++11之前,枚举没有像样的“类型”,如
int
,所以std::min,std::make_pair等不会猜测他们的模板参数…很遗憾,当值是switch语句中的标签时,这将不起作用。@Petr抱歉,不确定在这里告诉您什么。我几年没有使用C++了,所以我不知道这是不是代码>静态const <代码>或者什么。我应该让自己更清楚。我试图向阅读你们答案的任何人指出,尽管完全正确,但在某些情况下,这是行不通的。例如,如果要在开关中使用
作为标签,如
switch(x){case value:break;}
struct X
{
  enum : int64_t { VALUE = 100; }; // == static const int64_t VALUE = 100;
};