我可以根据 null 检查 C++ 迭代器吗?

Can I check a C++ iterator against null?

提问人:Zebrafish 提问时间:12/28/2016 最后编辑:Zebrafish 更新时间:7/13/2022 访问量:66092

问:

我在使用向量迭代器时遇到了问题。我在一些地方读到检查空迭代器是不可能的,检查迭代器的常用方法是在搜索后根据 vector.end() 检查它。例如:

vector< Animal* > animalList;

vector<Animal*>::iterator findInList(const type_info& type)
{
    // Loop through list of Animals, if Dog found, return iterator to it
}

auto it = findInList(typeid(Dog));
// With a pointer I can check if it's null, but with an iterator I have to check against animalList.end();

问题是容器可能是空的。使用迭代器,我无法返回 null 来指示容器为空或搜索失败。我可以返回vector::end(),但 cplusplus.com 说:

If the container is empty, vector::end() function returns the same as vector::begin()

然后对于 vector::begin(),它说:

If the container is empty, the returned iterator value shall not be dereferenced.

因此,如果我有一个空容器,vector::end() 和 vector::begin() 指向同一个地方,我认为我不能取消引用它,我什至不确定它是否指向分配的内存。

编辑:谢谢大家。正如您迭代的那样,vector::end() 或 vector::begin() 不会取消引用迭代器,我可以安全地检查 vector::end()。

C++ 指针 向量 迭代器 nullptr

评论

0赞 Barmar 12/28/2016
返回空向量的迭代器。当调用方循环迭代器时,循环将立即结束,并且他们永远不会取消引用迭代器。
0赞 jaggedSpire 12/28/2016
您是否试图避免公开您在内部使用的容器,因此犹豫是否要为用户提供一种方法来检查返回的值与容器本身的值?end
1赞 simon 12/28/2016
迭代器不是指针。
0赞 Drew Dormann 12/28/2016
“所以,如果我有一个空容器......我不认为我可以取消引用它“如果您返回的指针可能为 null,情况也是如此。
0赞 Zebrafish 12/28/2016
@jaggedSpire,现在必须。好吧,我希望该函数尽可能多地处理。我认为从答案中我理解我可以获得与 vector::end() 相同的行为检查,即与返回指针并检查 nullptr 相同。

答:

3赞 Mikel F 12/28/2016 #1

不可以,不能检查 NULL,因为它不是指针。返回并检查 .只有当迭代器不等于时,才应取消引用它。animalList.end()end()

30赞 paweldac 12/28/2016 #2

您不需要检查迭代器是否为 null,因为它永远不会为 null。您需要检查返回的迭代器是否与容器的位置不同。如果是,则可以通过 安全地取消对迭代器的引用。end()*it

如果容器为空,则不应取消引用返回的迭代器值。 因此,如果我有一个空容器,vector::end() 和 vector::begin() 指向同一个地方,我认为我不能取消引用它,我什至不确定它是否指向分配的内存。

不,检查不是取消引用迭代器。迭代器取消引用是通过 完成的,这意味着获取迭代器指向的对象的值。从同一容器中将迭代器检查到其他迭代器始终是安全的,取消引用不指向容器元素的迭代器是不安全的。if(myIt != container.end())*myIt

评论

0赞 Zebrafish 12/28/2016
啊,我明白我误会了。根据 .end() 检查迭代器并不是取消引用它,谢谢。
0赞 paweldac 12/28/2016
@TitoneMaurice如果我帮助将问题标记为已解答,它将在其他人的谷歌索引中可见,并且不会显示在未解答的问题列表中。谢谢。
0赞 Lightness Races in Orbit 12/28/2016
“将迭代器检查到其他迭代器始终是安全的”好吧,不,迭代器必须是有效的(这包括一次结束),并且它们必须引用同一个容器。
0赞 paweldac 12/28/2016
@LightnessRacesinOrbit更新了 anwser,其中包含有关同一容器的信息。没有 stl 算法会返回“one-past-the-end”迭代器。它将返回 end()。用户必须手动递增这样的迭代器,如果开发者想伤害自己,他总会想办法:)谢谢你指出来。
1赞 Lightness Races in Orbit 12/28/2016
end()返回 one-past-the-end 迭代器。它是超过容器有效范围末尾的迭代器。这是标准使用的术语,是主要参考网站使用的术语,也是我使用的术语!我以前从未听说过“过去结束迭代器”。
3赞 Vlad from Moscow 12/28/2016 #3

就这样检查

auto it = findInList( someInfo );

if ( it == animalList.end() ) std::cout << "not found";

评论

9赞 Lightness Races in Orbit 12/28/2016
这不是好的风格。你已经抽象了一个名为 的函数后面的容器,但现在你必须立即打破这个抽象,直接与容器进行比较。要么首先使用,要么找到另一种方法来表示未找到的情况。findInList.find
0赞 Vitalii 7/12/2022 #4

也许可以使用此解决方法,例如根据 NULL 值检查迭代器:

#include <iostream>
#include <vector>


int main()
{
    std::vector<int> vector_int = {1, 2, 3, 4};

    std::vector<int>::iterator vector_int_iterator = --vector_int.begin();

    while(vector_int_iterator != vector_int.end())
    {
        if(vector_int_iterator == --vector_int.begin())
        {
            std::cout 
                << "Doing some stuff only once before iterate through vector's elements" 
                << std::endl;
            vector_int_iterator++;
        }

        std::cout << *vector_int_iterator++ << std::endl;
    }
}

当我们必须多次循环运行时,它可能特别有用。