未定义的引用静态const int [英] Undefined reference to static const int

查看:174
本文介绍了未定义的引用静态const int的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天我遇到了一个有趣的问题。考虑这个简单的例子:

I ran into an interesting issue today. Consider this simple example:

template <typename T>
void foo(const T & a) { /* code */ }

// This would also fail
// void foo(const int & a) { /* code */ }

class Bar
{
public:
   static const int kConst = 1;
   void func()
   {
      foo(kConst);           // This is the important line
   }
};

int main()
{
   Bar b;
   b.func();
}

编译时出现错误:

Undefined reference to 'Bar::kConst'

现在,我很确定这是因为 static const int 没有在任何地方定义,这是有意的,因为根据我的理解,编译器应该能够在编译时进行替换,而不需要定义。然而,由于函数接受一个 const int& 参数,它似乎不是进行替换,而是更喜欢引用。我可以通过进行以下更改来解决此问题:

Now, I'm pretty sure that this is because the static const int is not defined anywhere, which is intentional because according to my understanding the compiler should be able to make the replacement at compile-time and not need a definition. However, since the function takes a const int & parameter, it seems to be not making the substitution, and instead preferring a reference. I can resolve this issue by making the following change:

foo(static_cast<int>(kConst));

我相信这现在迫使编译器创建一个临时int,然后传递一个引用,它可以在编译时成功执行。

I believe this is now forcing the compiler to make a temporary int, and then pass a reference to that, which it can successfully do at compile time.

我想知道这是否是故意的,或者我期望过多的gcc能够处理这种情况?

I was wondering if this was intentional, or am I expecting too much from gcc to be able to handle this case? Or is this something I shouldn't be doing for some reason?

推荐答案

这是有意的,9.4.2 / 4说: / p>

It's intentional, 9.4.2/4 says:


如果静态数据成员是const整数或const枚举类型,
它在类
定义中的声明指定一个
常量初始化器,它应该是一个
积分常数表达式(5.19)在
中,该成员可以出现在
积分常量表达式中。如果
程序中使用
成员,那么
成员仍然在
命名空间范围中定义

If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression (5.19) In that case, the member can appear in integral constant expressions. The member shall still be defined in a namespace scope if it is used in the program

当你通过const引用传递静态数据成员时,你使用它,3.2 / 2:

When you pass the static data member by const reference, you "use" it, 3.2/2:



除非出现需要整数
常量表达式的位置(见
5.19),是sizeof运算符的操作数(5.3.3),或者是
的操作数typeid运算符,表达式
不指定
多态类类型(5.2.8)的左值。如果
对象或非重载函数的名称出现在
潜在求值的表达式中,则使用

An expression is potentially evaluated unless it appears where an integral constant expression is required (see 5.19), is the operand of the sizeof operator (5.3.3), or is the operand of the typeid operator and the expression does not designate an lvalue of polymorphic class type (5.2.8). An object or non-overloaded function is used if its name appears in a potentially-evaluated expression.

事实上,当你通过值传递它时,或者在 static_cast 中,你使用它。这是因为GCC已经让你在一种情况下,但不是其他的钩子。

So in fact, you "use" it when you pass it by value too, or in a static_cast. It's just that GCC has let you off the hook in one case but not the other.

const引用的实际问题是 foo 在其获取其参数的地址的权限之内,并且例如与存储在全局中的来自另一调用的参数的地址进行比较。由于静态数据成员是一个唯一的对象,这意味着如果从两个不同的TU调用 foo(kConst),那么传递的对象的地址必须相同案件。

The practical problem with the const reference is that foo is within its rights to take the address of its argument, and compare it for example with the address of the argument from another call, stored in a global. Since a static data member is a unique object, this means if you call foo(kConst) from two different TUs, then the address of the object passed must be the same in each case. AFAIK GCC can't arrange that unless the object is defined in one (and only one) TU.

OK,所以在这种情况下 foo 是一个模板,因此定义在所有TU中都是可见的,所以也许编译器可以在理论上排除它对地址做任何事情的风险。但一般来说,你当然不应该使用不存在的对象的地址或引用; - )

OK, so in this case foo is a template, hence the definition is visible in all TUs, so perhaps the compiler could in theory rule out the risk that it does anything with the address. But in general you certainly shouldn't be taking addresses of or references to non-existent objects ;-)

这篇关于未定义的引用静态const int的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆