C ++ for-loop - size_type vs. size_t

时间:2011-01-31 10:14:46

标签: c++ vector for-loop size-type

C++ Primer一书的第(3)章中,有以下for循环将向量中的元素重置为零。

for (vector<int>::size_type ix = 0; ix ! = ivec.size(); ++ix)
ivec[ix] = 0;

为什么使用vector<int>::size_type ix = 0?我们不能说int ix = 0吗?在第二个表格中使用第一个表格有什么好处?

感谢。

4 个答案:

答案 0 :(得分:16)

C ++标准说,

 size_type  |  unsigned integral type  |  a type that can represent the size of the largest object in the
allocation model

然后它补充说,

  

容器的实现   在这个国际描述   标准允许假设   他们的Allocator模板参数   满足以下两个额外的   要求超出表32中的要求。

     
      
  • typedef成员指针,const_pointer,size_type和   difference_type是   需要分别为T *,T const *,size_t和ptrdiff_t
  •   

所以最有可能的是,size_typesize_t的typedef。

标准确实将其定义为,

template <class T> 
class allocator 
{
   public:
       typedef size_t size_type;
       //.......
};

因此,最重要的要点是:

  • size_typeunsigned积分,而int 必然 unsigned。 : - )
  • 它可以代表最大的索引,因为它是无符号的。

答案 1 :(得分:12)

是的,您可以使用int,但只有类型vector<int>::size_type保证其类型可用于索引所有向量元素。

它可能与int的大小相同,也可能不同。例如,在为64位Windows编译时,int为32位宽,而vector<int>::size_type为64位宽。

您可以使用vector<int>::size_type,而不是使用相当冗长的std::size_t,因为前者是后者的typedef。但是,如果您碰巧更改了容器类型,那么其size_type可能是另一种类型,如果代码使用std::size_t,则可能需要修改代码。

答案 2 :(得分:9)

vector<int>::size_type是一种类型,保证保持您可能拥有的最大vector的大小,因此可以保证让您索引vector的所有元素(因为索引从0变为size-1);它是所有vector方法中用于索引和大小的类型。

如果你有非常大的数组,这可能实际上是相关的,因为其他整数类型可能会溢出(如果它们是signed类型,事情会变得非常奇怪);即使你不会得到这么大的阵列,这可能很重要,它从根本上说是代码清洁的事情;此外,您的ix具有相同类型的ivec.size(),因此您不会收到有关比较有符号和无符号整数的警告。

背景vector<T>::size_type typedef通常是size_t(我在某处读到实际标准的隐式强加给它是size_t - 编辑:它根本不是隐含的,请参阅 @Nawaz 的答案),而这又是{{的返回类型1}}运算符。这隐含地说它可以保存C ++应用程序中可用的最大对象的大小,所以它肯定(只是)大到足以索引任何类型的数组。

实际上,我使用sizeof(在size_t中定义)作为C风格数组的索引,我认为这是一个很好的做法,原因完全相同。


顺便说一句,您可能也会忘记用于索引的类型,只需要使用迭代器:

<cstddef>

或使用迭代器+ for (vector<int>::iterator it = ivec.begin(); it != ivec.end(); ++it) *it = 0;

<algorithm>

这两个选项适用于任何容器std::fill(ivec.begin(), ivec.end(), 0); ,因此如果您决定更改容器类型,则不必更改代码中的任何内容。

使用ivec,您还可以使用vector方法(如其他答案所示):

assign

答案 3 :(得分:3)

您不应该使用int因为vector<int>::size_type是无符号类型,即向量使用无符号类型对其元素进行索引。 int但是是签名类型,混合有符号和无符号类型可能会导致奇怪的问题。 (虽然在你的例子中对小n来说不会有问题。)

请注意,我认为使用size_t(而不是T :: size_type)更清楚 - 减少输入并且应该适用于所有实现。

另请注意您发布的for循环:

for(size_t ix=0; ix != ivec.size(); ++ix) ...

最好写成:

for(size_t i=0, e=ivec.size(); i!=e; ++ix) ...

- 无需每次迭代调用size()。