循环中的 Stroustrup 和溢出 size_type

Stroustrup and overflowing size_type in a loop

我正在阅读 Bjarne Stroustrup 的 "Programming Principles and Practices using C++",我需要对我在第 25.5.3 节中发现的令人惊讶的一点进行澄清。作者声称,如果我们想遍历一个 std::vector,然后使用像

这样的循环变量
for (vector<int>::size_type i = 0; i < v.size(); ++i)

不如对 vector class:

使用迭代器安全
for (vector<int>::iterator p = v.begin(); p != v.end(); ++p)

因为,作为无符号类型,i 可能会溢出。他指出使用迭代器的循环没有这样的限制。我有点困惑,因为我了解到 size_type 保证足够大以表示可能的最大向量,因此 size_type 类型的变量永远不会在这样的循环中溢出。

编辑

更具体地说,他展示了一个在其他两个之前使用类型为 int 的循环变量的示例,然后在最后他指出:

"The size_type is guaranteed to be unsigned, so the first (unsigned integer) form has one more bit to play than the int version above. That can be significant, but it still gives only a single bit of range (doubling the number of iterations that can be done). The loop using iterators has no such limitation."

vector<T>::size() return 不是 vector<T>::size_type 吗?我没有看到任何限制。

vector::sizereturnsvector::size_type,因此从0开始的vector::size_type i在超过返回值之前不可能超过vector::size_type表示的最大值通过 vector::size。很安全。


because, being of an unsigned type, i could overflow.

如果这是直接引用,那么它是一个错误,并且已在第 2 版中修复,其中 iint。在那种情况下 i 可能会溢出。


就其价值而言,我找不到(第 2 版)Bjarne 声称其中一个比另一个更安全的部分。

他声称迭代器没有索引所具有的范围限制。这是真的。迭代器理论上可以支持无限大的范围。

使用size_type循环容器元素没有溢出的问题,但是容器接口首先支持size_type的事实导致size_type的选择限制了容器可以包含的元素范围。

嗯,是的,您引用的段落似乎间接暗示或暗示 size_type 可能存在问题。但我不认为这是作者的意图。

注意前一段说(回复:第二版)

So, technically, most of the loops in this book have been sloppy [...]. To avoid this problem we can use the size_type provided by vector, iterators, or a range-for-statement:

在本段中 size_type 提出了一个 解决方案 用于本书前面部分中使用的可能有问题的 int 循环。它被认为是 与循环的迭代器或 range-for 版本一起 的安全替代方案。


当有人尝试使用 std::size_t 对非基于数组的容器的元素进行计数或索引时,确实存在潜在的溢出(或范围不足)问题,例如 std::list、[=18] =]、std::map 等,而不是使用容器自己的 size_type。但这是一个略有不同的故事,即使它是相关的。