【问题标题】:Undefined reference to static const integral type对静态 const 整数类型的未定义引用
【发布时间】:2017-08-16 17:10:55
【问题描述】:

我对静态整数常量有一个奇怪的行为:

#include <iostream>
#include <inttypes.h>

class Test{
public:
 static const uint32_t Magic = 0x1123;
};

class DataStream{
public:
    template<typename T>
    DataStream& operator <<( const T& value )
    {
        std::cout << value << std::endl;
        return *this;
    }
};

int main()
{
    DataStream s;

    uint32_t a = Test::Magic;  // ok
    bool compare = ( a == Test::Magic ); // ok
    s << compare;
    s << a;
    s << Test::Magic;  // fail

    return 0;
}

我知道这样的常量应该在 .cpp 的类之外定义为

const uint32_t Test::Magic;

但奇怪的是,上面的代码在没有s &lt;&lt; Test::Magic; 行的情况下工作正常,并且只有当Magic 直接与模板operator &lt;&lt; 一起使用时才会产生错误。

更多错误undefined reference to 'Test::Magic' 出现在GCC 中,但没有出现在MSVC 中。

问题是为什么我应该在类之外定义Test::Magic(即使没有价值!!!),为什么我的代码在某些情况下即使没有这样的定义也能正常工作?

【问题讨论】:

  • 在这里工作:ideone.com/xzky2g
  • @drescherjm 我也在 ideone 上试过,我could reproduce 出了问题(不过我使用 C++14 编译它..)。
  • 对静态常量整数成员的引用通常会被编译器忽略(编译器知道编译时的值,所以它直接使用它)。不过,我忘记了 C++ 规范中允许/预期发生这种情况的位置。
  • 我在wandbox.org/permlink/ULLcTpSdd4IbUnNHrextester.com/VCPDT93931 用一些不同的编译器尝试这段代码
  • 嗯。不确定我在 ideone 中选择什么编译器。编辑:看起来像他们用于 c++14 的任何东西。

标签: c++


【解决方案1】:

作为一项规则,所有静态常量名称都应在 .cpp 文件中定义,如果它们是 ODR used。引用参数是ODR using 他们。但是,违反此规则是未定义行为,MSVC 不报告错误只是未定义行为的表现方式之一。

作为一个实际的考虑,当函数没有内联时,您可能会遇到错误,并且对于内联函数可能看不到它。我的猜测是,内联的工作方式与您用于这些编译器的优化级别不同。

【讨论】:

【解决方案2】:

§ 9.4.2 静态数据成员 [class.static.data]

  1. 如果非易失性 const 静态数据成员是整数或枚举类型,它在类定义中的声明可以指定 一个大括号或相等初始化器 [...] 成员如果被 odr 使用,仍应在命名空间范围内定义 (3.2) 在程序和命名空间范围定义中不得 包含一个初始化程序。

  2. [ 注意:对于程序中 odr 使用 (3.2) 的静态数据成员,应有确切的定义无需诊断。 ——尾注]

【讨论】:

    猜你喜欢
    • 2011-07-20
    • 1970-01-01
    • 1970-01-01
    • 2011-03-02
    • 2021-07-10
    相关资源
    最近更新 更多