C ++ STL - 为什么将一个将迭代器作为void函数返回的函数处理?

时间:2017-02-13 00:28:27

标签: c++ c++14

STL有很多返回迭代器的函数。例如,STL列表函数erase返回迭代器(C ++ 98和C ++ 11)。不过,我认为它被用作无效功能。即使是cplusplus.com网站也有一个包含以下代码的示例:

mylist.erase(it1, it2); 

不返回迭代器。不应该正确的语法如下?

std::list<int>::iterator iterList = mylist.erase(it1, it2)?

4 个答案:

答案 0 :(得分:8)

您不必在C ++中使用返回值。通常,返回的迭代器应该对该容器有一个新的有效迭代器很有用。但从语法上讲,它是正确的。请记住,删除后,it1it2将不再有效。

答案 1 :(得分:7)

  

不返回迭代器。不应该使用正确的语法   如下?

它确实返回一个迭代器,但就像任何其他函数一样,您可以忽略返回的值。如果你只想删除一个元素并且不关心返回的迭代器,那么你可以简单地忽略它。

实际上忽略返回值比您预期的更常见。可能忽略返回值的最常见位置是返回值的唯一目的是启用链接。例如,赋值运算符通常写为

Foo& operator=(const Foo& other){
    /*...*/
    return *this;
}

这样你就可以写出像a = b = c这样的东西。但是,当您只编写b = c时,通常会忽略该调用返回的值。另请注意,当您编写b = c时,这会返回一个值,但如果您只想进行此分配,则除了忽略返回值之外别无选择。

答案 2 :(得分:1)

实际原因远比你想象的要平庸。如果您无法忽略返回值,则需要将.erase()等许多函数拆分为两个版本:.erase()版本返回void而另一个版本.erase_and_return()返回迭代器的版本。你会从中获得什么?

答案 3 :(得分:1)

有时返回值有用。如果它们没用,则不必使用它们。

所有container.erase函数在新擦除的范围之后返回迭代器。对于非基于节点的容器,这通常(但并非总是)有用,因为范围内和之后的迭代器不再有效。

对于基于节点的容器,这通常是无用的,因为即使在擦除操作之后传入的第二个迭代器仍然有效。

无论如何,两者都返回迭代器。这允许在通用容器上工作的代码不必知道容器是否在擦除后维护有效的迭代器;它只能存储返回值,并且具有擦除后的有效迭代器。

C ++标准容器中的迭代器创建,销毁和复制都非常便宜;实际上,它们在实践中非常便宜,如果不使用它们,编译器可以完全消除它们。因此,返回未使用的迭代器可能没有运行时间成本。

这里不使用此返回值的程序在语义和语法上都可以是正确的程序。同时,其他语义和语法正确的程序将要求您使用该返回值。

最后,

mylist.erase(it1, it2);

这确实会返回一个迭代器。迭代器立即被丢弃(返回值仅作为未命名的临时值存在),并且编译器可能会优化它不存在。

但仅仅因为你没有存储一个返回值,并不意味着它不会被返回。