C++:“vector<int>::size_type 变量”——以这种方式声明的意义何在?

Posted

技术标签:

【中文标题】C++:“vector<int>::size_type 变量”——以这种方式声明的意义何在?【英文标题】:C++: "vector<int>::size_type variable" - what is the point of declaring in this way? 【发布时间】:2014-07-18 13:02:23 【问题描述】:

我认为这是一个非常基本的问题,但我无法弄清楚。

我习惯于在 C++ 中使用数组,但我现在开始学习向量。 我正在编写测试代码,遇到了一个问题。

首先,这是我制作的代码:

#include <iostream>
#include <vector>
#include <numeric>
using namespace std;

int main()
  vector<double> score(10);

  for(vector<double>::size_type i=0;i<20;i++) 
    cout<<"Enter marks for student #"<<i+1<<":"<<flush;
    cin>>score[i];
  

  double total = accumulate(score.begin(), score.end(),0);

  cout<<"Total score:"<<total<<endl<<"Average score:"<<total/score.size()<<flush;

  return 0;

在第 9 行的 for 句子中,我将 i 声明为 vector&lt;double&gt;::size_type 类型(因为有人告诉我这样做)。 我用 int 替换了上面所说的类型测试了代码,它工作得非常好。 为什么 vector&lt;double&gt;::size_typeint 更受欢迎?

【问题讨论】:

您当前的代码超出了向量的范围。如果您将 20 更改为 score.size(),您应该会收到有关有符号和无符号比较的警告。顺便说一句,您不需要调用flush,因为在读取输入之前会刷新输出。 我总是使用std::size_t。我认为这是允许的。如果没有,那么我有一个下午的重构要做! @Bathsheba,我所知道的所有实现都使 std::size_t 成为类型。当然,可能有一个没有。 @chris 我认为它在那里是因为分配器可以更改容器size_type 的类型。有一个不可忽略的可能性是我刚刚梦想的。 对不起,20 是我的错误,是 10。我不知道我为什么这样做 【参考方案1】:

size_type 保证足够大以支持最大的向量大小,vector::max_size()int 不是:在许多常见平台上,int 有 32 位,而 max_size() 远大于 231

如果您知道大小是(并​​且永远是)像 20 这样的小数字,那么您可以使用int 或任何其他整数类型而不是size_type。如果您要更改程序,例如从输入中读取大小,那么如果该值大于INT_MAX,则会出现可怕的错误;在使用size_type 时,它将继续为任何值工作,直到max_size(),您可以轻松地对其进行测试。

【讨论】:

是否有任何不使用std::size_t 的特定理由,即std::vectorsize_type 不仅仅是std::size_t 的别名的任何特定情况?我总是使用std::size_t 来表示数组/向量/任何索引和大小表示,因为它应该是用于此目的的标准/便携式类型。 @Manu343726:标准不保证size_type 将是std::size_t。但在实践中,总是如此。因此,是否使用std::size_tsize_type 取决于您希望在标准合规性方面有多“纯粹”。我个人觉得std::vector&lt;double&gt;::size_type 太长了。 它实际上很长,但这不是 typedef 和 C++11 的“类型别名”旨在简化的吗?使用它实际上是免费的 :)【参考方案2】:

嵌入类型vector&lt;double&gt;::size_type 与各种vector 方法的返回值相关,例如.size(),因此在这种情况下优先使用匹配类型(int = 0 通常会导致符号不匹配警告)。例如

for (vector<double>::size_type i = 0; i < score.size(); ++i)  // types match
  // ...


for (int i = 0; i < score.size(); ++i)  // types mismatch
  // ...

std::vector::size_type 需要足够大以表示容器中可以包含的最大元素数,在本例中为vector&lt;double&gt;::max_size()。一般来说,它映射到size_t

在您的情况下,没有明确的理由使用vector&lt;double&gt;::size_type(尽管从技术上讲使用size_type 会更好),因为循环从0 运行到20 并且两者都是int。因此,以下是可以的。

for (int i = 0; i < 20; ++i)  // loops 20 times
  // ...

补充说明:

支持基于迭代器的循环优于基于索引的循环:

for (vector<double>::iterator i = score.begin(); i != score.end(); ++i) 
  // ...

它没有被标记为 C++11,但如果可能的话,基于范围的 for 循环可以处理很多这样的问题。

for (double& i : score) 
  // ...

或者甚至使用带有 lambda 的 for_each

【讨论】:

【参考方案3】:

vectorsize_type 是矢量用来进行大小比较的。如果您有一个使用 int 作为计数器并与向量的实际大小进行比较的循环,您会从编译器收到有关有符号整数与无符号整数比较的警告:

for( int i=0; i<score.size(); i++ )  // <-- signed vs. unsigned comparisons
    // do something...

【讨论】:

【参考方案4】:

你的问题有两个。

首先,您正在写超出std::vector 末尾的内容——std::vector 有 10 个元素,而您正在写入 20 个元素。

为了解决这个问题,并遵循不要重复自己的原则,您需要按如下方式更改代码:

int main()
  std::vector<double> score(20);

  for(std::vector<double>::size_type i=0;i<score.size();i++) 

我将vector 放大并使用它的大小来确定要写入多少。

现在,当我们尝试用int 替换那个长子句时:

int main()
  std::vector<double> score(20);

  for(int i=0;i<score.size();i++) 

我们得到一个有符号/无符号的比较(可能):

i<score.size()

其中score.size()std::vector&lt;double&gt;::size_type 类型的无符号值,iint

编译器在这些情况下经常会给出警告,因为很容易得到无意义的结果(如果i 0,比较通常会导致负数比较大于正数!)另外,如果vector 的大小大于int 的最大值(在某些系统上,小至32767,通常至少2147483647,有时更大——这是编译器的值可以合理地为自己选择,C++ 标准没有完全指定它),循环将失败。

现在,虽然std::vector&lt;double&gt;::size() 的类型是std::vector&lt;double&gt;::size_type,但它(在我经历过的每个实现中)只是std::size_t。所以这是一种更简短的说法:

  for(std::size_t i=0;i<score.size();i++) 

std::size_t&lt;cstddef&gt; 中定义为旁白)。

如果你用 C++11 编程,你可以做得更好:

int i=0;
for(double& student:score) 
  std::cout<<"Enter marks for student #"<<++i<<":"<<std::flush;
  std::cin>>student;

这是一个基于范围的for循环,完全避免了索引问题。

【讨论】:

你的远程身体有问题。 @quentin 它只是需要更多的喘息空间 嘿,现在看起来好多了。但不会因为缺少声明的i 而编译;)

以上是关于C++:“vector<int>::size_type 变量”——以这种方式声明的意义何在?的主要内容,如果未能解决你的问题,请参考以下文章

c++中迭代器的问题为啥这样会报错?

在 C++ 中将字符串转换为向量

005. Longest Palindromic Substring

Longest Palindromic Subsequence

001两数之和

UVALive 6530 Football (水