在临时字符串上使用基于范围的循环时为空字符?

Posted

技术标签:

【中文标题】在临时字符串上使用基于范围的循环时为空字符?【英文标题】:Null character when using range-based loop over temporary string? 【发布时间】:2021-11-08 12:57:47 【问题描述】:

当我使用基于范围的 for 循环遍历临时 std::string(右值?)时,似乎有一个额外的字符,即空终止符 \0

当字符串不是临时的(而不是左值?)时,没有多余的字符。为什么?

    std::map<char, int> m;

    for (char c : "bar") m[c] = 0;

    for (auto [c, f] : m) 
        if (c == '\0') std::cout << "this is a null char, backward slash zero" << std::endl;
        std::cout << c << std::endl; 
    

输出:

this is a null char, backward slash zero

a
b
r

(注意空行,\0 正在打印)

相比:

    std::map<char,int> m;
    
    std::string s = "bar";
    
    for (char c : s) m[c] = 0;    
    
    for (auto [c, f] : m) 
        if (c == '\0') std::cout << "this is a null char, backward slash zero" << std::endl;
        std::cout << c << std::endl; 
    

输出:

a
b
r

【问题讨论】:

【参考方案1】:

因为"bar" 不是std::string,而是一个char 数组(const char[4]),包含4 个元素,包括最后一个空字符。 IE。 c-style string literal:

空字符('\0'L'\0'char16_t() 等)始终附加到字符串文字:因此,字符串文字 "Hello" 是包含字符 'H'、@ 的 const char[6] 987654334@、'l''l''o''\0'

对于临时的std::strings,它将按您的预期工作,即不包含空字符。

for (char c : std::string"bar") m[c] = 0;

或者

using namespace std::string_literals;
for (char c : "bar"s) m[c] = 0;

顺便说一句,作为@HolyBlackCat suggested,您还可以使用std::string_view(C++17 起),当从 c 样式的字符串文字构造时,它不会包含以 null 结尾的字符。例如

for (char c : std::string_view"bar") m[c] = 0;

或者

using namespace std::literals;
for (char c : "bar"sv) m[c] = 0;

【讨论】:

也可以使用string_view来避免堆分配。

以上是关于在临时字符串上使用基于范围的循环时为空字符?的主要内容,如果未能解决你的问题,请参考以下文章

Part6 数组指针与字符串 6.2 数组作为函数的参数 6.3对象数组 6.4基于范围的for循环

分段错误:循环打印时为 11

在python IndexError中使用for循环反转字符串:字符串索引超出范围[重复]

循环字符串时如何插入临时表 - Oracle - PL/SQL

shell基础(五)for循环及循环终止命令

创建 C 子字符串:使用赋值运算符 VS strncopy 循环,哪个更好?