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<double>::size_type
类型(因为有人告诉我这样做)。
我用 int
替换了上面所说的类型测试了代码,它工作得非常好。
为什么 vector<double>::size_type
比 int
更受欢迎?
【问题讨论】:
您当前的代码超出了向量的范围。如果您将 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::vector
的size_type
不仅仅是std::size_t
的别名的任何特定情况?我总是使用std::size_t
来表示数组/向量/任何索引和大小表示,因为它应该是用于此目的的标准/便携式类型。
@Manu343726:标准不保证size_type
将是std::size_t
。但在实践中,总是如此。因此,是否使用std::size_t
或size_type
取决于您希望在标准合规性方面有多“纯粹”。我个人觉得std::vector<double>::size_type
太长了。
它实际上很长,但这不是 typedef 和 C++11 的“类型别名”旨在简化的吗?使用它实际上是免费的 :)【参考方案2】:
嵌入类型vector<double>::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<double>::max_size()
。一般来说,它映射到size_t
。
在您的情况下,没有明确的理由使用vector<double>::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】:vector
size_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<double>::size_type
类型的无符号值,i
是int
。
编译器在这些情况下经常会给出警告,因为很容易得到无意义的结果(如果i
0,比较通常会导致负数比较大于正数!)另外,如果vector
的大小大于int
的最大值(在某些系统上,小至32767
,通常至少2147483647
,有时更大——这是编译器的值可以合理地为自己选择,C++ 标准没有完全指定它),循环将失败。
现在,虽然std::vector<double>::size()
的类型是std::vector<double>::size_type
,但它(在我经历过的每个实现中)只是std::size_t
。所以这是一种更简短的说法:
for(std::size_t i=0;i<score.size();i++)
(std::size_t
在 <cstddef>
中定义为旁白)。
如果你用 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 变量”——以这种方式声明的意义何在?的主要内容,如果未能解决你的问题,请参考以下文章
005. Longest Palindromic Substring