为什么string::find返回size_type而不是迭代器?

32

为什么在C++中,string::find返回size_type而不是iterator

如果string::replacestring::insert等函数接受迭代器作为输入,则这样做很有意义,因此您可以查找某个字符并立即将返回的迭代器传递给replace等函数。

此外,std::find返回一个迭代器--为什么std::string::find不同呢?


主要是出于历史原因。同时,这种糟糕的设计让我在上次技术面试中失败了,因为我混淆了“迭代器”和“size_t”。 - JP Zhang
4个回答

28

当Stroustrup向标准委员会介绍STL时,标准库全新的字符串类的设计已完成。委员会喜欢STL并开始将其纳入标准,因此调整了他们已经同意的很多内容(可能还延迟了标准的发布一两年)。

除其他变化外,迭代器作为事后想法被添加到已经完成的字符串类中。通过查看各种采用/返回位置的字符串成员,你可以看到这一点——这是索引和迭代器的混合使用。

有时候很难猜测为什么一些成员函数只有接受索引版本,而有些则有接受迭代器版本。然而,在std::basic_string<>::find()的情况下,似乎很容易:由于std::find()已经返回一个迭代器,std::basic_string<>::find()就保留原样了。


2
@dehmann:从历史的角度来看待这个问题:他们只在STL算法无法处理迭代器的情况下添加了处理迭代器的成员函数。由于std::find()对字符串的处理非常完美,因此没有必要再为字符串类添加另一个返回迭代器的查找函数。因此,std::basic_string<>::find()保持不变。 - sbi
@sbi 假设一个人正在搜索子字符串而不是单个字符,我认为使用 std::search() 而不是 std::find() 是获得迭代器结果的方法。但这可能不如 std::basic_string<>::find() 高效(取决于 C++17 之后的搜索器)。 - Andrew Moylan
@Andrew,请帮我解决这个问题。为什么一个旨在在另一个序列中搜索一系列项目的函数可能比一个旨在在另一个字符序列中搜索一系列字符的函数效率低呢? - sbi
我所指的是经验观察,即std::basic_string<>::find()显然是O(n*m),而使用std::search(),如果合适的话,可以选择O(n+m)类型的搜索器。 - Andrew Moylan
@AndrewMoylan:我的回答和评论是针对90年代中后期字符串类的设计。搜索器是在C++17中引入的新特性。 - sbi
显示剩余2条评论

7

从find中获取数字可能更有用,因为然后您可以使用[]运算符或substr()来获取刚刚搜索到的字符。

此外,如果您想要一个迭代器,您总是可以执行begin() + pos


4
所以你的意思是,string::find 的糟糕接口实际上很好,因为它与 string::substr 的糟糕接口相互配合得很好? ;) - Praxeolitic
当我只想获取字符串的前两个字母时,我不想在迭代器上瞎搞。 - shoosh
喜欢它:begin() + pos - fchen
让我们谈谈当你使用 string::substr()string::find() 时,string::npos 返回的快乐。 - alextoind

3
所有字符串函数都基于索引操作,一些函数(例如replace()insert())还额外支持迭代器。因此,find()的结果可以直接用于这些函数。由于不能有两个只是返回类型不同(一个返回迭代器,一个返回索引)的find()函数,所以必须选择一个。

0

我认为这是因为通常字符串成员使用索引而不是迭代器,这使得使用返回值变得容易。如果您想获取迭代器,您始终可以使用std::find


我只是想说,std::vector 本质上也是基于索引工作的,并且在搜索某些内容时不会返回 size_type -- 但是后来我想起来 vector 根本没有 find()。这让你想知道为什么 string 有它... - Frank
1
@dehmann:由于历史原因,它有这个。std::string是第一个(然后是std::basic_string),然后STL和其迭代器出现了。当决定将STL合并到标准中时,它实际上已经接近最终化了。(STL的合并延误了一年左右。)实际上,已经有在使用中的std::basic_string实现。因此,更改被保持最小,并且大多数只是添加。 - sbi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接