【问题标题】:Why must a string be constructed at run-time? [duplicate]为什么必须在运行时构造字符串? [复制]
【发布时间】:2015-05-29 02:29:10
【问题描述】:

C-Strings 或std::strings 可以创建为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 不能是问题核心的文字。

【问题讨论】:

  • 我认为原因在另一个答案中给出:因为'std::basic_string'有一个非平凡的析构函数。
  • 这两个概念是无关的。您实际上是在询问 std::string 是否是文字类型。不是。
  • 您还遗漏了错误消息的重要部分:“... 'std::basic_string' 不是文字,因为: ... 'std::basic_string'有一个非平凡的析构函数”,这使得它成为另一个问题的重复。
  • 显而易见的答案是它需要调用operator new,这作为编译时操作实际上没有意义。堆可能甚至还没有构建,等等。
  • 这个问题有什么依据吗?这似乎是一个 XY 问题。

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


【解决方案1】:

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

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

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

那么为什么不直接将std::string 设为文字类型呢?

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

这需要对核心语言进行大规模的更改才能做出一些东西 像在编译时可用的动态内存,或者做一些事情 像 VLA/ARB 并允许它们在文字类型中。鉴于剧烈 Rapperswil Evolution 不仅对 N4025(类 运行时大小),但任何与 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 条):

  • 它有一个微不足道的析构函数,
  • 每个构造函数调用和非静态数据成员(如果有)的大括号或等号初始化器中的完整表达式都是常量表达式 (5.19),
  • 它是一种聚合类型 (8.5.1) 或至少有一个constexpr 构造函数或构造函数模板不是复制或移动 构造函数
  • 它的所有非static 数据成员和基类都是文字类型。

std::string 不符合该标准。

【讨论】:

  • @downvoter 请解释一下,任何技术错误,我是否漏掉了一点?
  • @downvoter 我也希望看到这个反对票被删除,因为我觉得这很专业地回答了我要问的问题。如果有理由拒绝投票,我当然希望看到评论解释原因。
  • 我经常想知道是否可以重载std::string 的构造函数,以便在使用字符串字面量(或其他适用的常量表达式)调用的情况下,它足够短启用 SSO,constexpr 版本会加入。
  • @5gon12eder 听起来很糟糕,代码不应该因标准库优化而中断
  • @MattMcNabb 如果这被实施,那当然意味着标准必须为 SSO 制定规则。这是否是一个好主意还有待商榷,但我认为这是一件有趣的事情。
【解决方案2】:

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

【讨论】:

  • 你是说这是std::string 不是文字类型的唯一原因,一个类有几个标准。
猜你喜欢
  • 2018-07-25
  • 2011-03-17
  • 2019-08-13
  • 2020-09-03
  • 2011-07-06
  • 2013-06-02
  • 1970-01-01
  • 2010-12-20
  • 2018-01-23
相关资源
最近更新 更多