当前位置: 首页 > 知识库问答 >
问题:

为什么必须在运行时构造字符串?[副本]

长孙深
2023-03-14

C字符串或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不是文字。也就是说:为什么必须在运行时构造字符串?

正如所指出的,这个问题的部分答案是:是否可以在constexpr中使用std::string?但它并没有触及为什么std::string不能成为问题的核心。

共有2个答案

颜哲彦
2023-03-14

您不能使用constexpr,因为std::string没有一个简单的析构函数。检查CPP参考上的要求。

郭琦
2023-03-14

有一个constepr字符串的建议:编译时字符串:std::string_literal,它说:

与std::字符串一样,std::string_literal的目的是为处理文本提供一个方便的实用程序。与std::字符串不同,std::string_literal的实例化是文字类型,因此可以在编译时使用。也就是说,它可能是一个Constexpr对象的类型,也可能是一个Constexpr函数的参数、返回值或局部变量的类型

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

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

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

这将需要大量的核心语言更改,以使动态内存在编译时可用,或者使VLA/ARB之类的东西在文本类型中可用。考虑到Rapperswil Evolution对N4025(运行时大小的类)以及任何与VLA/ARB模糊不清的事物的强烈负面反应,我们可以预期这种情况不会很快发生,因此这种想法是不可能的。

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

为什么不能应用到std::字符串,但可以到char数组

应用于对象的constexpr应应用于不适用于std::string但适用于const char数组的文本类型。根据C 11标准草案第7.1.5节[dcl.constexpr](重点放在未来):

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

第3.9节[basic.types]:

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

并包括:

  • 标量类型;或
  • 文字类型的数组

算术类型是标量类型,包括char,它覆盖了const char的数组

至于课程:

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

  • 它有一个简单的析构函数

std::string不符合该标准。

 类似资料:
  • 或修饰符不允许与构造函数一起使用。为什么?我试过阅读标准文档,但没有很好地理解它。

  • 可能的重复: 为什么this()和super()必须是构造函数中的第一条语句? 为什么子类构造函数必须显式调用超类构造函数?这是什么原因呢?

  • 问题内容: 我正在学习python并试图将github问题转换为可读形式。使用有关如何将JSON转换为CSV的建议?我想出了这个: 其中“ issues.json”是包含我的github问题的json文件。当我尝试运行它时,我得到 我在这里想念什么?哪些是“字符串索引”?我确定一旦完成这项工作,我就会遇到更多问题,但是就目前而言,我只是喜欢这个工作! 当我将陈述调整为 我得到的是…“问题”-所以我

  • 我知道不同的平台有不同的UI需求,但为什么我必须下载源代码并自己编译它呢?为什么我不能为我的平台下载一个可运行的版本?

  • 问题内容: 在Jackson中,当您使用注释构造函数时,必须使用注释其参数。所以这个构造函数 变成这个: 我不明白为什么有必要。你能解释一下吗? 问题答案: Jackson必须知道以什么顺序将字段从JSON对象传递给构造函数。使用反射无法在Java中访问参数名称-这就是为什么您必须在注释中重复此信息的原因。

  • 问题内容: 在Java的构造函数中,如果要调用另一个构造函数(或超级构造函数),则它必须是该构造函数的第一行。我认为这是因为不允许您在其他构造函数运行之前修改任何实例变量。但是,为什么不能在构造函数委派之前使用语句,以便计算另一个函数的复杂值?我想不出任何正当的理由,在一些实际案例中,我编写了一些丑陋的代码来解决此限制。 所以我只是想知道: 有此限制的充分理由吗? 有没有计划在将来的Java版本中