为什么必须在运行时构造字符串?

时间:2015-03-25 12:11:52

标签: c++ c++11 literals stdstring constexpr

C-Strings或std::string可以创建为constexpr还是必须在运行时创建?

使用gcc 4.9.2我可以这样做:

constexpr const char foo[] = "blee";

(可悲的是,2013年11月的客户技术预览版不允许Visual Studio支持这一点:https://stackoverflow.com/a/29255013/2642059

但即使使用gcc 4.9.2,我也不能这样做:

constexpr const std::string foo = "blee";

我收到错误:

error: the type 'const string {aka const std::basic_string<char>}' of constexpr variable 'foo' 
       is not literal

 constexpr const std::string foo = "blee";
                                   ^
note: 'std::basic_string<char>' is not literal because:
     class basic_string
           ^
note:   'std::basic_string<char>' has a non-trivial destructor

但我想更多地澄清为什么 std::string不是文字。也就是说:为什么必须在运行时构造一个字符串?

正如所指出的那样,这个问题可以部分回答:Is it possible to use std::string in a constexpr?但它没有涉及为什么std::string不能成为问题核心的文字。

2 个答案:

答案 0 :(得分:28)

有一个 constexpr 字符串的提案:Compile-Time String: std::string_literal,它说:

  

std::string_literal一样,std::string的目的是   提供便于使用文本的实用程序。不像   std::stringstd::string_literal的实例化是文字   类型等可以在编译时使用。也就是说,它可能是类型   一个constexpr对象,它可能是一个参数的类型,   constexpr函数的返回值或局部变量

这也证实确实std::string不是文字类型

那么为什么不让std::string成为文字类型?

我们从上面的提案中得到一个暗示,为什么这不可能:

  

这需要进行大规模的核心语言更改才能创造出一些东西   就像在编译时可用的动态内存,或者做出一些东西   像VLA / ARB一样,允许他们使用文字类型。鉴于暴力   Rapperswil Evolution对N4025的不良反应(Classes   运行时大小),但任何模糊地类似于VLA / ARB的东西,我们   可以预期这不会很快发生,所以这个想法是一个   不可取。

std::string需要动态内存,这在编译时是不可用的。

为什么constexpr不能应用于std :: string但可以应用于char数组

应用于对象的

constexpr应该应用于文字类型,它不适用于std::string但适用于const char数组。从草案C ++ 11标准部分7.1.5 [dcl.constexpr] 强调我的前进):

  

对象声明中使用的constexpr说明符声明了   对象为const。这样的对象应具有文字类型和应当   被初始化。如果它是由构造函数调用初始化的那个   call应该是一个常量表达式(5.19)。 [...]

以及3.9 [basic.types]

部分
  

类型是文字类型,如果它是:

并包括:

  
      
  • 标量类型;或
  •   
  • 一个文字类型数组
  •   

算术类型是标量类型,包括 char ,它涵盖了const char

的数组

和课程:

  

具有以下所有属性的类类型(第9节):

     
      
  • 它有一个简单的析构函数,
  •   
  • 非静态数据成员(如果有)的brace-or-equal-initializers中的每个构造函数调用和完全表达式都是常量表达式(5.19),
  •   
  • 它是聚合类型(8.5.1)或至少有一个constexpr构造函数或构造函数模板,它不是复制或移动   构造函数
  •   
  • 所有非static数据成员和基类都是文字类型。
  •   

std::string不符合该标准。

答案 1 :(得分:5)

您不能使用constexpr,因为 std :: string 没有简单的destructor。检查cppreference的要求。