我编写了一个函数,它需要向量上的一对 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()?我该怎么做才能获得所需的行为,即异常或立即返回?
我已阅读有关迭代器的 C++ 文档,并且知道当测试为空时
(testing.begin() <= testing.end())进行评估,因为空向量的开始和结束是相同的。True
的确。testing.begin() == testing.end()当向量为空时。
为什么
testing.end()-1不评估小于testing.begin()?
因为迭代器不是整数。递减迭代器使其引用容器中的前一个元素。之前没有元素begin。当end等于时begin,则前面也没有元素end。end您无法在空容器中递减迭代器。当为空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]即a和b都包含在范围内,如何表示空范围并不明显(因为[a,a]是包含 1 个元素的范围)。有多种方法可以处理它,并且 C++ 约定并不是唯一可能的选择,但坚持使用它比使用其他约定更简单。
| 归档时间: |
|
| 查看次数: |
113 次 |
| 最近记录: |