我正在阅读Bjarne Stroustrup的“使用C ++进行编程原理和实践”,我需要澄清一下我在第25.5.3节中找到的令人惊讶的一点。作者声称如果我们想迭代std::vector
,那么使用像
for (vector<int>::size_type i = 0; i < v.size(); ++i)
比使用vector
类的迭代器更安全:
for (vector<int>::iterator p = v.begin(); p != v.end(); ++p)
因为属于无符号类型,i
可能会溢出。他声明使用迭代器的循环没有这样的限制。我有点困惑,因为我了解到size_type
保证足够大以代表最大可能的向量,因此size_type
类型的变量永远不会在这样的循环中溢出。
修改
更具体地说,他提出了一个使用类型为int
的循环变量的示例,然后在另外两个之前,他说:
“size_type
保证是无符号的,因此第一个(无符号整数)形式比上面的int
版本多一个比特。这可能很重要,但它仍然只给出一个范围的单位(可以完成的迭代次数加倍)。使用迭代器的循环没有这样的限制。“
vector<T>::size()
不返回vector<T>::size_type
吗?我没有看到任何限制。
答案 0 :(得分:6)
嗯,是的,你引用的段落确实暗示或暗示size_type
可能会有问题。但我不认为这是作者的意图。
请注意,前一段说明(re:Second Edition)
因此,从技术上讲,本书中的大多数循环都是草率的[...]。为避免此问题,我们可以使用
size_type
提供的vector
,迭代器或范围 -for
- 语句:
在本段中,size_type
提供了一个解决方案,用于本书前几节中使用的可能有问题的int
循环。它被称为一个安全的替代在一起与迭代器或范围 - 循环版本。
当有人试图使用std::size_t
来计算或索引非基于数组的容器的元素时,确实存在潜在的溢出(或范围不足)问题,例如std::list
,std::deque
,std::map
等,而不是使用容器自己的size_type
。但这是一个略有不同的故事,即使它是相关的。
答案 1 :(得分:4)
vector::size
会返回vector::size_type
,因此从{0}开始的vector::size_type i
在超过vector::size_type
返回的值之前,不可能超过vector::size
可表示的最大值。这很安全。
因为是无符号类型,我可能会溢出。
如果这是直接引用,那么这是一个错误,并且在i
为int
的第二版中已得到修复。在这种情况下,i
可能会溢出。
对于它的价值,我没有找到(第2版)Bjarne声称其中一个比另一个更安全
的部分。他声称迭代器没有索引所具有的范围限制。这是事实。迭代器理论上可以支持无限大范围。
使用size_type
循环容器元素没有溢出问题,但容器接口首先支持size_type
的事实有效地导致选择size_type
来限制范围容器可以包含的元素。