为什么我可以定义一个 constinit 的 std::string 实例?如果一个对象需要动态初始化,constinit不是被禁止了吗?

问题描述 投票:0回答:2

cppreference提到,如果初始化包含动态初始化部分,则在 C++20 中使用 constinit 时程序格式错误。

我只是想知道为什么下面的代码会编译:

constinit std::string str = "Hello";

由于

std::string
类涉及用于存储字符的动态内存分配,因此看起来很矛盾。由于动态部分,这不应该被禁止吗?

尝试使用标志进行编译

-std=C++20
,程序编译得很好,但不应该这样。

c++ c++20 constinit
2个回答
11
投票
如果字符串足够短,则常见的

std::string

 实现不会在堆上分配(这称为“短字符串优化”或“SSO”)。

由于 SSO 可以容纳的确切字符数(如果有)取决于实现,因此您可能不应该依赖它,或者至少应该研究三大标准库如何处理这个问题。


10
投票
这个答案是对@HolyBlackCat 的答案的补充。

正如您所解释的成功编译的原因:

constinit std::string str = "Hello";
是由于短字符串优化 (SSO)。

这在这 2 个演示中得到了演示:

    上面的行可以在所有 3 个主要编译器上编译。
  1. 请参阅
    演示1
  2. 将字符串的大小增加到超过 SSO 可以处理的范围(在本例中为
  3. "Hello1234567890123456789012345678901234567890"
    ),会导致所有 3 个编译器出现编译错误
    (例如 gcc 问题:
    error: 'constinit' variable 'str' does not have a constant initializer
    )。
    请参阅
    演示2
请注意,SSO 支持的具体长度取决于实现。

在上面的演示中,我只是增加了长度,直到失败为止。 SSO 的最大长度可能会在未来版本中更改。

© www.soinside.com 2019 - 2024. All rights reserved.