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
不能成为问题核心的文字。
答案 0 :(得分:28)
有一个 constexpr 字符串的提案:Compile-Time String: std::string_literal,它说:
与
std::string_literal
一样,std::string
的目的是 提供便于使用文本的实用程序。不像std::string
,std::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的要求。