为什么标准将end()定义为超过末端的一个,而不是在实际的末端?


当前回答

end()指向结束后的位置,使用for循环迭代集合很容易:

for (iterator it = collection.begin(); it != collection.end(); it++)
{
    DoStuff(*it);
}

如果end()指向最后一个元素,循环将更加复杂:

iterator it = collection.begin();
while (!collection.empty())
{
    DoStuff(*it);

    if (it == collection.end())
        break;

    it++;
}

其他回答

end()指向结束后的位置,使用for循环迭代集合很容易:

for (iterator it = collection.begin(); it != collection.end(); it++)
{
    DoStuff(*it);
}

如果end()指向最后一个元素,循环将更加复杂:

iterator it = collection.begin();
while (!collection.empty())
{
    DoStuff(*it);

    if (it == collection.end())
        break;

    it++;
}

半封闭范围的迭代器习惯用法[begin(), end())最初是基于普通数组的指针算术。在这种操作模式下,函数将被传递一个数组和一个大小。

void func(int* array, size_t size)

当你有这些信息时,转换到半封闭范围[begin, end)是非常简单的:

int* begin;
int* end = array + size;

for (int* it = begin; it < end; ++it) { ... }

要使用全封闭范围,就更难了:

int* begin;
int* end = array + size - 1;

for (int* it = begin; it <= end; ++it) { ... }

由于指向数组的指针在c++中是迭代器(并且语法设计允许这一点),调用std::find(array, array + size, some_value)要比调用std::find(array, array + size - 1, some_value)容易得多。


另外,如果使用半封闭范围,可以使用!=操作符检查结束条件,因为(如果操作符定义正确)<表示!=。

for (int* it = begin; it != end; ++ it) { ... }

然而,对于完全封闭的范围来说,做到这一点并不容易。你只能使用<=。

c++中唯一支持<和>操作的迭代器是随机访问迭代器。如果必须为c++中的每个迭代器类编写<=操作符,则必须使所有迭代器完全可比较,并且如果c++使用全封闭范围,则创建功能较差的迭代器(例如std::list上的双向迭代器,或操作iostreams的输入迭代器)的选择就会减少。

如果容器是空的,begin() == end()。 因此,c++程序员倾向于在循环条件中使用!=而不是<(小于) 让end()指向超出末端的位置很方便。

为什么标准将end()定义为超过末端的一个,而不是在实际的末端?

因为:

它避免了对空范围的特殊处理。对于空范围,begin()等于 结束()& 它使得遍历元素的循环的结束条件简单:循环简单 只要没有到达end(),就继续。

因为这样

size() == end() - begin()   // For iterators for whom subtraction is valid

你也不用做一些尴尬的事情,比如

// Never mind that this is INVALID for input iterators...
bool empty() { return begin() == end() + 1; }

你不会不小心写出错误的代码

bool empty() { return begin() == end() - 1; }    // a typo from the first version
                                                 // of this post
                                                 // (see, it really is confusing)

bool empty() { return end() - begin() == -1; }   // Signed/unsigned mismatch
// Plus the fact that subtracting is also invalid for many iterators

另外:如果end()指向一个有效的元素,find()会返回什么? 你真的想要另一个名为invalid()的成员返回无效迭代器吗? 两个迭代器已经够痛苦的了……

哦,看看这个相关的帖子。


另外:

如果结束在最后一个元素之前,如何在真正的结束处插入()?!