繁体   English   中英

C++20 中的 constexpr std::string,它是如何工作的?

[英]constexpr std::string in C++20, how does it work?

显然, constexpr std::string尚未添加到GCClibstdc++中(截至 GCC v11.2)。

这段代码:

#include <iostream>
#include <string>


int main( )
{
    constexpr std::string str { "Where is the constexpr std::string support?"};

    std::cout << str << '\n';
}

不编译:

time_measure.cpp:37:31: error: the type 'const string' {aka 'const std::__cxx11::basic_string<char>'} of 'constexpr' variable 'str' is not literal
   37 |         constexpr std::string str { "Where is the constexpr std::string support?"};
      |                               ^~~
In file included from c:\mingw64\include\c++\11.2.0\string:55,
                 from c:\mingw64\include\c++\11.2.0\bits\locale_classes.h:40,
                 from c:\mingw64\include\c++\11.2.0\bits\ios_base.h:41,
                 from c:\mingw64\include\c++\11.2.0\ios:42,
                 from c:\mingw64\include\c++\11.2.0\ostream:38,
                 from c:\mingw64\include\c++\11.2.0\iostream:39,
                 from time_measure.cpp:2:
c:\mingw64\include\c++\11.2.0\bits\basic_string.h:85:11: note: 'std::__cxx11::basic_string<char>' is not literal because:
   85 |     class basic_string
      |           ^~~~~~~~~~~~
c:\mingw64\include\c++\11.2.0\bits\basic_string.h:85:11: note:   'std::__cxx11::basic_string<char>' does not have 'constexpr' destructor

我的问题是,当字符串包含超过 16 个char时(因为 GCC 的 SSO 缓冲区大小为 16),这些字符串将如何在后台工作? 有人可以给我一个简短的解释吗? 一个简单的构造函数会在堆栈上创建字符串 object 并且从不使用动态分配吗?

这段代码:

    std::cout << "is_trivially_constructible: "
              << std::boolalpha << std::is_trivially_constructible<const std::string>::value << '\n';

打印这个:

is_trivially_constructible: false

现在在这里使用constexpr (显然不使用 GCC v11.2 编译):

    std::cout << "is_trivially_constructible: "
              << std::boolalpha << std::is_trivially_constructible<constexpr std::string>::value << '\n';

结果会像下面true吗?

is_trivially_constructible: true

C++20 支持在 constexpr 时间分配,只要分配在时间常数评估结束时完全解除分配。 因此,例如,这个非常愚蠢的例子在 C++20 中是有效的:

constexpr int f() {
    int* p = new int(42);
    int v = *p;
    delete p;
    return v;
}

static_assert(f() == 42);

但是,如果您忘记delete p; 在那里,那么f()不再是一个常量表达式。 不能泄漏 memory。 例如,gcc 拒绝:

<source>:2:24: error: '(f() == 42)' is not a constant expression because allocated storage has not been deallocated
    2 |     int* p = new int(42);
      |                        ^

回到你的问题, std::string可以在constexpr中很好地处理长字符串——正如你所料,通过为其分配 memory 。 但是,C++20 constexpr 规则仍然受到这条规则的限制,即所有分配必须在评估结束时清理。 换句话说,所有分配都必须是瞬态的 - C++ 尚不支持非瞬态 constexpr 分配。

结果,您的原始程序

int main( )
{
    constexpr std::string str { "Where is the constexpr std::string support?"};
}

无效,即使 gcc 支持constexpr string (就像它现在在主干上所做的那样),因为str需要被销毁。 但这很好:

constexpr int f() {
    std::string s = "Where is the constexpr std::string support?";
    return s.size();
}

static_assert(f() > 16);

而它不会在 C++17 中编译。


在 C++23 中仍然不支持非瞬态 constexpr 分配。 这是一个令人惊讶的棘手问题。 但是,希望很快。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM