如何使用 RandomAccessIterator 检查 std::vector 是否为空?

Tim*_*Tim 2 c++ iterator std

我编写了一个函数,它需要向量上的一对 RandomAccessIterators 来对其进行排序。这很好用。我编写了一个表现出奇怪行为的测试用例。

我的功能的“模拟”:

#include <vector>
#include <iostream>
#include <cassert>

int main(){

    std::vector<int> testing = std::vector<int>(0);

    assert(testing.begin() <= (testing.end()-1)); //why no fail?

    std::cout << (testing.begin() <= (testing.end())); //prints 1
    std::cout << (testing.begin() <= (testing.end()-1)); //prints 1 unexpectedly

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当向量testing为空时,我希望函数不执行任何操作抛出异常。我不知道哪一个更好。欢迎提出建议。

我已阅读有关迭代器的 C++ 文档,并且知道当测试为空时(testing.begin() <= testing.end()) 进行评估,因为空向量的开始和结束是相同的。True

为什么testing.end()-1的计算结果不小于testing.begin()?我该怎么做才能获得所需的行为,即异常或立即返回?

for*_*818 5

我已阅读有关迭代器的 C++ 文档,并且知道当测试为空时(testing.begin() <= testing.end())进行评估,因为空向量的开始和结束是相同的。True

的确。testing.begin() == testing.end()当向量为空时。

为什么testing.end()-1不评估小于testing.begin()

因为迭代器不是整数。递减迭代器使其引用容器中的前一个元素。之前没有元素begin。当end等于时begin,则前面也没有元素endend您无法在空容器中递减迭代器。当为空testing.end() -1时未定义。testing

迭代end器很特殊,因为即使容器不为空,它也不会引用容器中的元素。相反,它指向最后一个元素之后的一个。这就是为什么例如在具有 1 个元素的容器中,您可以将end迭代器递减一次以使其等于begin

我该怎么做才能获得所需的行为,即异常或立即返回?

如果你想检查向量是否为空,你可以检查 iftesting.begin() == testing.end()或使用它的empty()方法。未定义的行为不会引发异常或导致立即返回,它是未定义的。

我编写了一个函数,它需要向量上的一对 RandomAccessIterators 来对其进行排序。这很好用。我编写了一个表现出奇怪行为的测试用例。

您没有展示该函数,但要对一系列元素进行排序,您至少需要两个迭代器。一个到范围的开始,一个到范围的结束。在函数内部,您可以比较这两个迭代器以查看范围是否为空:

 template <typename Iterator>
 void foo(Iterator a, Iterator b) {
        // check for empty range
        if (a == b) return;
        // else do something
        // ...
 }
Run Code Online (Sandbox Code Playgroud)

如果调用者将无效的迭代器传递给该函数,则该函数对此无能为力,但需要修复调用代码。


附:

到目前为止,我的函数需要 begin() 和 end()-1 作为迭代器

C++ 约定是使用半开范围 ,[a,b)其中a包含但不包含b,并且[a,a)表示空范围。它可能会有所不同,但事实就是如此,它使您的循环看起来像:

 for( auto it = a; a != b; ++b) ...
Run Code Online (Sandbox Code Playgroud)

对于闭区间 ,[a,b]ab都包含在范围内,如何表示空范围并不明显(因为[a,a]是包含 1 个元素的范围)。有多种方法可以处理它,并且 C++ 约定并不是唯一可能的选择,但坚持使用它比使用其他约定更简单。