Stroustrup并在循环中溢出size_type

时间:2017-03-07 19:14:01

标签: c++ iterator size-type

我正在阅读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吗?我没有看到任何限制。

2 个答案:

答案 0 :(得分:6)

嗯,是的,你引用的段落确实暗示或暗示size_type可能会有问题。但我不认为这是作者的意图。

请注意,前一段说明(re:Second Edition)

  

因此,从技术上讲,本书中的大多数循环都是草率的[...]。为避免此问题,我们可以使用size_type提供的vector,迭代器或范围 - for - 语句:

在本段中,size_type提供了一个解决方案,用于本书前几节中使用的可能有问题的int循环。它被称为一个安全的替代在一起与迭代器或范围 - 循环版本。

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

答案 1 :(得分:4)

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

  

因为是无符号类型,我可能会溢出。

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

对于它的价值,我没有找到(第2版)Bjarne声称其中一个比另一个更安全

的部分。

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

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