为什么 `std::string::find()` 不是 return 失败时的结束迭代器?
Why does `std::string::find()` not return the end iterator on failures?
我发现 std::string::find
的行为与标准 C++ 容器不一致。
例如
std::map<int, int> myMap = {{1, 2}};
auto it = myMap.find(10); // it == myMap.end()
但是对于一个字符串,
std::string myStr = "hello";
auto it = myStr.find('!'); // it == std::string::npos
为什么失败的 myStr.find('!')
return myStr.end()
而不是 std::string::npos
?
由于std::string
与其他容器相比有些特殊,我想知道这背后是否有真正的原因。
(令人惊讶的是,我在任何地方都找不到任何人对此提出质疑)。
首先,众所周知,std::string
界面臃肿且不一致,请参阅 Herb Sutter 关于此主题的 Gotw84。但是,尽管如此,std::string::find
return 索引背后还是有原因的:std::string::substr
。这个方便的成员函数对索引进行操作,例如
const std::string src = "abcdefghijk";
std::cout << src.substr(2, 5) << "\n";
您可以实现 substr
,使其接受字符串中的迭代器,但这样一来我们就不需要等待很长时间,因为大声抱怨 std::string
不可用且违反直觉。因此,鉴于 std::string::substr
接受索引,您如何在上述输入字符串中找到 'd'
第一次出现的索引,以便打印出从该子字符串开始的所有内容?
const auto it = src.find('d'); // imagine this returns an iterator
std::cout << src.substr(std::distance(src.cbegin(), it));
这也可能不是您想要的。因此我们可以让 std::string::find
return 一个索引,这里我们是:
const std::string extracted = src.substr(src.find('d'));
如果您想使用迭代器,请使用 <algorithm>
。他们允许您将上述内容作为
auto it = std::find(src.cbegin(), src.cend(), 'd');
std::copy(it, src.cend(), std::ostream_iterator<char>(std::cout));
这是因为std::string
有两个接口:
- 通用的基于迭代器的接口在所有容器
上找到
std::string
特定的 index 基于接口
std::string::find
是基于 index 的界面的一部分,因此 returns indices.
使用std::find
使用基于通用迭代器的接口。
如果您不想使用基于索引的界面(不要这样做),请使用 std::vector<char>
。
我发现 std::string::find
的行为与标准 C++ 容器不一致。
例如
std::map<int, int> myMap = {{1, 2}};
auto it = myMap.find(10); // it == myMap.end()
但是对于一个字符串,
std::string myStr = "hello";
auto it = myStr.find('!'); // it == std::string::npos
为什么失败的 myStr.find('!')
return myStr.end()
而不是 std::string::npos
?
由于std::string
与其他容器相比有些特殊,我想知道这背后是否有真正的原因。
(令人惊讶的是,我在任何地方都找不到任何人对此提出质疑)。
首先,众所周知,std::string
界面臃肿且不一致,请参阅 Herb Sutter 关于此主题的 Gotw84。但是,尽管如此,std::string::find
return 索引背后还是有原因的:std::string::substr
。这个方便的成员函数对索引进行操作,例如
const std::string src = "abcdefghijk";
std::cout << src.substr(2, 5) << "\n";
您可以实现 substr
,使其接受字符串中的迭代器,但这样一来我们就不需要等待很长时间,因为大声抱怨 std::string
不可用且违反直觉。因此,鉴于 std::string::substr
接受索引,您如何在上述输入字符串中找到 'd'
第一次出现的索引,以便打印出从该子字符串开始的所有内容?
const auto it = src.find('d'); // imagine this returns an iterator
std::cout << src.substr(std::distance(src.cbegin(), it));
这也可能不是您想要的。因此我们可以让 std::string::find
return 一个索引,这里我们是:
const std::string extracted = src.substr(src.find('d'));
如果您想使用迭代器,请使用 <algorithm>
。他们允许您将上述内容作为
auto it = std::find(src.cbegin(), src.cend(), 'd');
std::copy(it, src.cend(), std::ostream_iterator<char>(std::cout));
这是因为std::string
有两个接口:
- 通用的基于迭代器的接口在所有容器 上找到
std::string
特定的 index 基于接口
std::string::find
是基于 index 的界面的一部分,因此 returns indices.
使用std::find
使用基于通用迭代器的接口。
如果您不想使用基于索引的界面(不要这样做),请使用 std::vector<char>
。