c++ - 使用向量时的无符号整数或迭代器?
问题描述
我目前正在和一些朋友一起做一个 c++ 学校项目。
在我在 C++ 中使用向量之前,我做了这样的事情来使用它们:
unsigned int i = 0;
while (i != myVector.size())
{
doSomething(myVector[i]);
i++;
}
但是在这个项目中,我的朋友看到我使用这样的向量并不高兴,并要求我使用迭代器。我真的不喜欢迭代器,因为它们的语法很难记住,但我的朋友说使用它们更好,因为它工作得更快。由于我们在一个包含大量向量的大型项目中工作,因此使用迭代器至关重要。
时间已经过去了,即使我仍然不记得它们的语法,我仍在使用它们,但我想看看迭代器方法是否真的比“unsigned int”方法更快。
所以我做了这两个程序:
第一个使用 unsigned int 方法的程序:
#include <vector>
#include <string>
#include <iostream>
int main()
{
std::string str = "This is a string";
int i = 0;
std::vector<std::string> vec;
while (i != 10000000)
{
vec.push_back(str);
i++;
}
unsigned int j = 0;
while (j != vec.size())
{
std::cout << vec[j] << std::endl;
j++;
}
return (0);
}
第二个程序使用迭代器方法:
#include <vector>
#include <string>
#include <iostream>
int main()
{
std::string str = "This is a string";
int i = 0;
std::vector<std::string> vec;
while (i != 10000000)
{
vec.push_back(str);
i++;
}
std::vector<std::string>::iterator it;
it = vec.begin();
while (it != vec.end())
{
std::cout << *it << std::endl;
it++;
}
return (0);
}
正如您所看到的,两个程序将首先创建一个大小为 10 000 000 的向量(我放了一个很大的大小,所以如果时间上有差异,它会更容易注意到),然后我将在矢量但使用两种不同的方法。
我在 linux 上使用 time 来了解每个程序的执行时间,如下所示:
time ./a.out
结果如下:
无符号整数方法:
real 0m39,391s
user 0m5,463s
sys 0m21,108s
迭代器方法:
real 0m39,436s
user 0m5,972s
sys 0m20,652s
和......这是同一时间?!两者之间只有不到 1 秒的差异可以忽略不计,它是一个包含 1000 万个字符串的向量。
所以我想知道这两种方法之间真的有区别吗?迭代器真的更好用吗?
解决方案
使用迭代器的主要原因不是性能,而是更少的错误可能性和更具表现力的代码。比较这个
unsigned int i = 0;
while (i != myVector.size())
{
doSomething(myVector[i]);
i += 2;
}
或者
unsigned int start = myVector.size() + 42;
for (unsigned int i = start; i != myVector.size(); ++i){
doSomething(myVector[i]);
}
和
for (const auto& e : myVector) {
doSomething(e);
}
基于范围的 for 循环使使用迭代器变得尽可能简单(您甚至看不到迭代器,但它们在幕后使用)。当您手动管理索引时,有数百万种方法会出错,迭代器可能有 2 或 3 个。
为了您的性能比较:由于向量将其元素存储在连续内存中,因此向量迭代器可以是普通指针。您认为开销主要是语法糖,使您能够编写更好的代码。因此,您没有看到太大的差异也就不足为奇了。
附言
我经常使用它 我有点自信不会犯太多错误
使用整数迭代数组是上个世纪的事情。它不安全,导致难以检测错误,并且可以轻松调用未定义的行为。编写代码来表达你想要做什么,而不是指示你的处理器。如果您想为向量的每个元素做一些事情,您应该使用基于范围的 for 循环或更旧的std::for_each
:
std::for_each(myVector.begin(),myVector.end(),doSomething);
它没有手动使用索引的任何缺点(您发现上述循环中的错误了吗?)并且具有看起来相同的优点,无论容器myVector
实际上是什么,它包含什么类型的元素,或者doSomething
实际上是什么(它可以是自由函数、仿函数、lambda,您可以选择)。
推荐阅读
- python - 如何在加权平均中避免 NaN?
- git - Jenkins结帐后无法读取文件
- libgdx - LIBGDX 对话框文本按钮
- google-chrome-extension - 使用 background.js 与一些外部网站进行通信,然后在该网站上执行 content.js
- firebase - 这是比赛条件吗?
- python - python argparser 使用 nargs 为单个选项捕获冒号分隔的输入
- python - 用python正则表达式替换多行
- java - Constructor Jeans 不能应用给定类型
- css - 如何在缩略图中显示完整图片而不是裁剪一张?
- arrays - 函数的输出没有正确存储