在临时字符串上使用基于范围的循环时为空字符?
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::string
s,它将按您的预期工作,即不包含空字符。
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循环
在python IndexError中使用for循环反转字符串:字符串索引超出范围[重复]