Ijaz Ahmad Asked: 2024-10-04 14:43:52 +0800 CST2024-10-04 14:43:52 +0800 CST 2024-10-04 14:43:52 +0800 CST 为什么我可以定义一个 constinit 的 std::string 实例?如果对象需要动态初始化,constinit 不是被禁止的吗? 772 cppreference提到,如果初始化包含动态初始化部分,则在 C++20 中使用 constinit 时程序格式不正确。 我只是想知道为什么下面的代码可以编译: constinit std::string str = "Hello"; 由于std::string该类涉及用于存储字符的动态内存分配,因此这似乎是矛盾的。由于动态部分,这不应该被禁止吗? 尝试使用标志进行编译-std=C++20,程序编译正常,但事实并非如此。 c++ 2 个回答 Voted Best Answer HolyBlackCat 2024-10-04T15:16:21+08:002024-10-04T15:16:21+08:00 std::string如果字符串足够短,常见的实现就不会在堆上分配(这称为“短字符串优化”或“SSO”)。 由于 SSO 中可容纳的字符的确切数量(如果有)取决于实现,因此您可能不应该依赖它,或者至少应该研究三大标准库如何处理这个问题。 wohlstad 2024-10-04T15:30:56+08:002024-10-04T15:30:56+08:00 这个答案是对@HolyBlackCat答案的补充。 正如那里解释的那样,您成功编译的原因如下: constinit std::string str = "Hello"; 是由于短字符串优化(SSO)。 这两个演示证明了这一点: 上面这行代码可以在所有 3 个主流编译器上编译。 参见demo1。 将字符串的大小增加到 SSO 无法处理的范围("Hello1234567890123456789012345678901234567890"在本例中),会导致所有 3 个编译器出现编译错误 (例如 gcc 问题error: 'constinit' variable 'str' does not have a constant initializer:)。 参见demo2。 请注意,SSO 支持的具体长度取决于实现。 在上面的演示中,我只是增加了长度,直到失败。SSO 的最大长度可能会在未来版本中发生变化。
std::string
如果字符串足够短,常见的实现就不会在堆上分配(这称为“短字符串优化”或“SSO”)。由于 SSO 中可容纳的字符的确切数量(如果有)取决于实现,因此您可能不应该依赖它,或者至少应该研究三大标准库如何处理这个问题。
这个答案是对@HolyBlackCat答案的补充。
正如那里解释的那样,您成功编译的原因如下:
是由于短字符串优化(SSO)。
这两个演示证明了这一点:
参见demo1。
"Hello1234567890123456789012345678901234567890"
在本例中),会导致所有 3 个编译器出现编译错误(例如 gcc 问题
error: 'constinit' variable 'str' does not have a constant initializer
:)。参见demo2。
请注意,SSO 支持的具体长度取决于实现。
在上面的演示中,我只是增加了长度,直到失败。SSO 的最大长度可能会在未来版本中发生变化。