c++ - 将向量元素复制到向量对
问题描述
在我的 C++ 代码中,
vector <string> strVector = GetStringVector();
vector <int> intVector = GetIntVector();
所以我把这两个向量组合成一个向量,
void combineVectors(vector<string>& strVector, vector <int>& intVector, vector < pair <string, int>>& pairVector)
{
for (int i = 0; i < strVector.size() || i < intVector.size(); ++i )
{
pairVector.push_back(pair<string, int> (strVector.at(i), intVector.at(i)));
}
}
现在这个函数是这样调用的,
vector <string> strVector = GetStringVector();
vector <int> intVector = GetIntVector();
vector < pair <string, int>> pairVector
combineVectors(strVector, intVector, pairVector);
//rest of the implementation
combineVectors函数使用循环将其他 2 个向量的元素添加到向量对中。我怀疑这是一种有效的方法,因为这个函数被调用了数百次,传递不同的数据。这可能会导致性能问题,因为每次它都会通过循环。
我的目标是将“一次性”中的两个向量复制到向量对中。即,不使用循环。我不确定这是否可能。
有没有更好的方法在不影响性能的情况下实现这一目标?
解决方案
您已阐明数组将始终具有相同的大小。这是一个先决条件。
所以,你的情况如下。这里有向量 A,那里有向量 B。您无法保证向量 A 使用的实际内存和向量 B 使用的实际内存是否彼此相邻。他们可能在任何地方。
现在您将这两个向量组合成第三个向量 C。同样,不能保证向量 C 的内存在哪里。
因此,就优化而言,您几乎没有什么可使用的。您没有任何额外的保证。这是非常基本的:你有两个字节块,这两个块需要复制到其他地方。而已。这就是必须要做的事情,这就是一切的归结,没有其他方法可以完成它,除了完全这样做。
但是可以做一件事来让事情变得更快一点。向量通常会以增量步骤为其值分配内存,最初会保留一些额外的空间,随着值被一个接一个地添加到向量中,并最终达到向量的保留大小,向量现在必须获取一个新的更大的内存块,将向量中的所有内容复制到更大的内存块,然后删除旧块,然后才将下一个值添加到向量中。然后循环再次开始。
但是您提前知道要向向量添加多少值,因此您只需reserve
提前指示向量 () 足够大小,这样它就不必在向其添加值时重复自身增长. 在您现有的for
循环之前,只需:
pairVector.reserve(pairVector.size()+strVector.size());
现在,for
循环将继续并插入pairVector
保证有足够空间的新值。
还有一些其他的事情是可能的。由于您已声明两个向量将始终具有相同的大小,因此您只需检查其中一个向量的大小:
for (int i = 0; i < strVector.size(); ++i )
下一步:at()
执行边界检查。这个循环确保它i
永远不会越界,所以at()
的边界检查也是一些你可以安全地摆脱的开销:
pairVector.push_back(pair<string, int> (strVector[i], intVector[i]));
下一步:使用现代 C++ 编译器,编译器应该能够自动优化掉这里的几个冗余临时对象和临时副本。您可能需要稍微帮助编译器,并使用emplace_back
() 而不是push_back
() (假设 C++11 或更高版本):
pairVector.emplace_back(strVector[i], intVector[i]);
回到循环条件,在循环strVector.size()
的每次迭代中进行评估。现代 C++ 编译器很可能会将其优化掉,但以防万一您还可以帮助编译器size()
仅检查一次向量:
int i=strVector.size();
for (int i = 0; i < n; ++i )
这确实是一个延伸,但它可能会增加一些额外的执行时间。这里几乎所有明显的优化。实际上,在这里获得最多的是使用reserve()
. 其他优化可能会有所帮助,但这一切都归结为将一定数量的字节从内存中的一个区域移动到另一个区域。没有真正的特殊方法可以做到这一点,这比其他方式更快。
推荐阅读
- spring - Spring OAuth2 资源类没有被调用
- ruby-on-rails-5.1 - 为什么捆绑器没有解决法拉第依赖性?
- swift - 错误:表达式列表中的预期表达式
- html-lists - onclick 获取除法
- r - 从r中条件句的输出中删除引号
- php - 在 PHP 中创建 Soap 身份验证请求
- apache-camel - Apache Camel 消息交换不等待响应
- ngx-charts - 如何根据时间线选择更改 ngx-charts-line-chart 中的 xAxisTickFormatting?
- powershell - 从两个单独的集合创建一份报告
- database - 如果应用于第二个表的列,则选择带有 where 子句的查询会非常慢