【问题标题】:C++ inline initialization of a static const char*静态 const char* 的 C++ 内联初始化
【发布时间】:2014-07-04 10:37:54
【问题描述】:

为什么我无法在头文件中初始化静态 const char*? 在我的代码中,我的类标题中有:

static const char* xml_ID_TAG;

在 cpp 中:

const char* Class::xml_ID_TAG = "id";

xml_ID_TAG 变量包含 XML 文档的属性字符串。 由于它是静态、常量、原始类型(char*)等...我不明白为什么编译器禁止编写类似的东西:

static const char* xml_ID_TAG = "id";

我使用的是 MSVC2013 编译器,上面的示例给出了错误:“错误:具有类内初始化程序的成员必须是 const”

【问题讨论】:

  • 只有static const 整数成员可以在类体内定义。这是为了防止违反 ODR。

标签: c++


【解决方案1】:

一般来说,您必须在一个翻译单元中定义您的静态成员,并且该语言通过禁止您在周围的类定义中为此类成员编写初始化程序来帮助强制执行此操作:

struct T
{
   static int x = 42;
   // ^ error: ISO C++ forbids in-class initialization of
   // non-const static member 'T::x'
};

但是,为方便起见,对常量做了一个特殊的例外:

struct T
{
   static const int x = 42;
   // ^ OK
};

请注意,在大多数情况下,您仍然需要定义常量(最好放在 .cpp 文件中):

const int T::x;

[C++11: 9.4.2/3]:] 如果非易失性const static 数据成员是整数或枚举类型,它在类定义中的声明可以指定一个brace-or-equal-initializer,其中每个initializer-clause 是一个 assignment-expression 是一个常量表达式 (5.19)。可以在类定义中使用 constexpr 说明符声明文字类型的 static 数据成员;如果是这样,它的声明应指定一个 brace-or-equal-initializer,其中作为 assignment-expression 的每个 initializer-clause 都是一个常量表达式。 [ 注意: 在这两种情况下,成员都可能出现在常量表达式中。 —结束注释] 如果该成员在程序中odr-used (3.2) 并且命名空间范围定义不应包含初始化器,则该成员仍应在命名空间范围内定义.


现在,您的成员不是int,甚至const char* const 也不是“整体类型”:

struct T
{
   static const char* const str = "hi";
   // ^ error: 'constexpr' needed for in-class initialization of
   // static data member 'const char* const T::str' of non-integral type
};

但它“文字类型”;你的结果是,如果你这样写:

static constexpr const char* const xml_ID_TAG = "id";
//     ^^^^^^^^^             ^^^^^

你应该没事的。 (注意you will still need to define ituntil C++17。)

这可能更有意义:为什么要更改指针?

【讨论】:

  • 不,我尝试了最后一个解决方案(静态 constexpr const char * const foo="foo"),如果我没有定义它,在某些情况下它会给我链接错误。
  • @galinette 是的you still need to define it(虽然不是从 C++17 开始!)。谢谢,会澄清的。
【解决方案2】:

因为它是 [...] const” - 不。

您需要const char* const - 假设您使用的是 C++11。

否则你必须把定义放在cpp文件中。

见:How to initialize a static const member in C++?

【讨论】:

    【解决方案3】:

    因为字符串文字(例如"id")是按文件编译单元存储的。因此,如果它们位于头文件中,则为包含它的每个源文件存储不同的实例。因此,您的“初始化”正在尝试为#includes 的每个编译单元将不同的值存储在static 变量中..

    【讨论】:

      猜你喜欢
      • 2011-04-18
      • 1970-01-01
      • 2016-05-10
      • 2012-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-18
      • 2012-02-02
      相关资源
      最近更新 更多