为什么在类体

时间:2017-07-19 12:43:34

标签: c++ c++14

我正在使用c ++ 14。 我需要在我的类中使用静态const字符串。但是当我写作

class myClass
{
     static constexpr const std::string S="aa";
}

它无法编译。编译器(g ++)的结果是

type 'const string {aka const std::__cxx11::basic_string<char>}' of constexpr variable 'S::S' is not literal

如果我用char指针编写它,如:

class myClass
{
     static constexpr const *char S="aa";
}

它被编译。

我知道字符串可以在课外初始化。 我的问题是为什么没有编译第一个变体,第二个变量。我想知道标准说什么。

1 个答案:

答案 0 :(得分:4)

char基本类型(参考3.9.1基本类型[basic.fundamental],草案n4296 for C ++ 14)。它既没有构造函数也没有析构函数,可以在constexpr中使用。

另一方面,std::string是类类型。更确切地说,它是basic_string的专业化,即basic_string<char>。并且basic_string类有很多构造函数,包括在代码中使用const char *参数的构造函数,但没有一个被声明为constexpr,因此您无法构建{{1} }}。这是有道理的,因为constexpr std::string的创建远非微不足道,包括char数组的动态分配:

std::string
     

......分配的副本   由s

指向其第一个元素的数组

但恕我直言,正确的方法是宣布一个数组:

basic_string(const charT* s, const Allocator& a = Allocator());

顺便说一下,静态数据成员应该在它们的类定义之外定义,如果它们稍后在程序中使用的话。实现通常允许在类定义之外不定义整数常量或指针(无论如何,一个定义规则不需要诊断,未定义的行为允许预期结果),但严格的C ++语义不能。 / p>

来自n4296草案的C ++ 14草案:9.4.2静态数据成员[class.static.data]§3

  

如果非易失性const静态数据成员是整数或枚举类型,则其在类中声明   definition可以指定一个大括号或者相等的初始化器,其中每个初始化器子句都是assignmentexpression   是一个常数表达式(5.20)。可以在。中声明文字类型的静态数据成员   使用constexpr说明符的类定义;如果是这样,其声明应指定一个支撑或等于初始化器   其中作为赋值表达式的每个initializer子句都是一个常量表达式。 [注意:两者都有   在这些情况下,成员可能出现在常量表达式中。 - 后注]成员仍应定义   如果在程序中使用odr-used(3.2)并且命名空间作用域定义不在,则在命名空间作用域中   包含初始化程序。

相关问题