C++ for-loop - size_type vs. size_t

Sim*_*ity 17 c++ for-loop vector size-type

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

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

它为什么用vector<int>::size_type ix = 0?我们不能说int ix = 0吗?在第二种形式上使用第一种形式有什么好处?

谢谢.

Naw*_*waz 17

C++标准说,

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

然后它补充说,

允许本国际标准中描述的容器实现假设其分配器模板参数满足表32中的以下两个附加要求.

  • typedef成员指针,const_pointer,size_type和difference_type必须分别为T*,T const*,size_t和ptrdiff_t

所以最有可能的,size_type是一个typedef size_t.

标准确实将其定义为,

template <class T> 
class allocator 
{
   public:
       typedef size_t size_type;
       //.......
};
Run Code Online (Sandbox Code Playgroud)

因此,最重要的要点是:

  • size_typeunsigned不可或缺的,同时int不是 一定 unsigned.:-)
  • 它可以代表最大的索引,因为它是无符号的.


Dan*_*ger 13

是的,您可以使用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.

  • 更重要的是,size_type可能永远不会是int.它通常是size_t(unsigned int). (3认同)
  • `int`的大小取决于实现.例如,对于VisualC++,请参见此处:http://msdn.microsoft.com/en-us/library/s3f49ktz(VS.80).aspx.如您所见,`int`是32位,但指针是64位.另见http://blogs.msdn.com/oldnewthing/archive/2005/01/31/363790.aspx (2认同)
  • *您可以使用 std::size_t 而不是使用相当冗长的 vector&lt;int&gt;::size_type,因为前者是拿铁咖啡的 typedef* 不是真的。它*可能*相同,但没有要求。 (2认同)

Mat*_*lia 9

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

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

背景:vector<T>::size_type通常是typedeffor size_t(我读到某个地方实际上标准隐含地强加它size_t- 编辑:它根本不隐含,请参阅@Nawaz的答案),反过来,它是sizeof运算符的返回类型.这隐含地说它可以保存C++应用程序中可用的最大对象的大小,因此它肯定(仅)足以索引任何类型的数组.

实际上,我也使用size_t(定义<cstddef>)作为C风格数组的索引,我认为这是完全相同的理由.


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

for (vector<int>::iterator it = ivec.begin(); it != ivec.end(); ++it)
    *it = 0;
Run Code Online (Sandbox Code Playgroud)

或者使用迭代器+ <algorithm>:

std::fill(ivec.begin(), ivec.end(), 0);
Run Code Online (Sandbox Code Playgroud)

这两个选项适用于任何容器ivec,因此如果您决定更改容器类型,则不必更改代码中的任何内容.

随着vector您还可以使用assign方法(如在一些其他答案建议):

ivec.assign(ivec.size(), 0);
Run Code Online (Sandbox Code Playgroud)