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

C++ 为什么必须在运行时构造字符串?,c++,c++11,literals,stdstring,constexpr,C++,C++11,Literals,Stdstring,Constexpr,C字符串或std::strings是否可以创建为constexpr,还是必须在运行时创建 使用gcc 4.9.2,我可以做到: constexpr const char foo[] = "blee"; (遗憾的是,2013年11月的客户技术预览版不允许Visual Studio支持此功能:) 但即使使用gcc 4.9.2,我也无法做到这一点: constexpr const std::string foo = "blee"; 我得到一个错误: error: the type 'const s

C字符串或std::strings是否可以创建为
constexpr
,还是必须在运行时创建

使用gcc 4.9.2,我可以做到:

constexpr const char foo[] = "blee";
(遗憾的是,2013年11月的客户技术预览版不允许Visual Studio支持此功能:)

但即使使用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
错误:constexpr变量'foo'的类型'const string{aka const std::basic_string}'
不是字面意思
constexpr const std::string foo=“blee”;
^
注意:“std::basic_string”不是文字,因为:
类基本字符串
^
注意:“std::basic_string”有一个非平凡的析构函数
但我想进一步澄清为什么
std::string
不是文字。也就是说:为什么必须在运行时构造字符串?


正如所指出的,这个问题可以部分地用以下方式来回答:但它没有涉及为什么
std::string
不能成为问题的核心。

您不能使用constepr,因为std::string没有一个简单的问题。检查CPPFRENCE上的要求。

有一个constexpr字符串的提案,上面写着:

std::string\u literal
的目的与
std::string
类似,是为了 提供用于处理文本的便利实用程序。不像
std::string
,std::string\u literal的实例化是一个literal 类型,因此可以在编译时使用。也就是说,它可能是 一个
constexpr
对象,它可能是一个参数的类型,
constexpr
函数的返回值或局部变量

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

那么为什么不把
std::string
变成一个文本类型呢?

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

这将需要对核心语言进行大规模的更改,以实现某种功能 类似于编译时可用的动态内存,或者用来制作某些东西 类似于VLA/ARB,并允许它们以文本类型出现。考虑到暴力 Rapperswil进化的负面反应不仅仅是N4025(类 但任何模糊地类似于VLA/ARBs的东西,我们 我们可以预期这种情况不会很快发生,所以这个想法是一个好主意 非起动器

std::string
需要编译时不可用的动态内存

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

应用于对象的
constexpr
应应用于不适用于
std::string
但适用于
const char
数组的文本类型。从草案C++11标准部分
7.1.5
[dcl.constexpr](重点放在后面):

对象声明中使用的
constexpr
说明符声明 对象为
常量
。此类对象应具有文字类型,并应 被初始化。如果它是由构造函数调用初始化的,那么 调用应为常量表达式(5.19)。[……]

并从第3.9节[基本类型]中:

如果类型是:

包括:

  • 标量类型;或
  • 文字类型的数组
算术类型是标量类型,包括char,它包含
const char

至于课程:

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

  • 它有一个简单的析构函数,
  • 非静态数据成员(如果有)的大括号或相等初始值设定项中的每个构造函数调用和完整表达式都是常量表达式(5.19)
  • 它是聚合类型(8.5.1),或至少有一个
    constexpr
    构造函数或构造函数模板不是复制或移动 构造函数
    ,以及
  • 它的所有非静态数据成员和基类都是文本类型

std::string
不符合该标准。

我认为另一个答案给出了原因:因为“std::basic_string”有一个非平凡的析构函数。这两个概念不相关。本质上,您是在询问
std::string
是否为文本类型。不是。您还遗漏了错误消息的一个重要部分:“…'std::basic_string'不是文字,因为:…'std::basic_string'有一个非平凡的析构函数”这使得这个问题与另一个问题重复。显而易见的答案是,它需要调用
操作符new
,这对于编译时操作来说是没有意义的。堆可能还没有被构造,等等。这个问题有什么理由吗?这似乎是一个XY问题。你是说这是
std::string
不是文本类型的唯一原因,一个类有几个标准。@downvoter请解释一下,有没有技术错误,我有没有漏掉一点?@downvoter我也希望看到这个downvoter被删除,因为我觉得这很好地回答了我的问题。如果投票失败是有原因的,我当然希望看到一条解释原因的评论。我经常想知道是否有可能重载
std::string
的构造函数,以便在使用足够短的字符串文本(或其他适用的常量表达式)调用它时启用SSO,
constexpr
版本将跳入。@5gon12eder听起来很可怕,根据标准库,代码不应该中断optimization@MattMcNabb如果实现了这一点,这当然意味着该标准必须为SSO制定规则。这是否是一个好主意还有待讨论,但我认为这是一件值得思考的事情。