在我的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个向量的元素添加到向量对中。我怀疑这是一种有效的方法,因为此函数被称为传递不同数据的时间的数百倍。这可能会导致性能问题,因为它每次都经过循环。
我的目标是将“ 一遍 ”中的两个向量都复制到向量对中。即不使用循环。不知道这是否有可能。
在不影响性能的情况下,还有更好的方法吗?
答案 0 :(得分:0)
您已经阐明了数组的大小将始终相等。这是前提条件。
因此,您的情况如下。您在这里有向量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()
。其他优化可能会有所帮助,但最终归结为将一定数量的字节从内存中的一个区域移至另一区域。并没有真正特殊的方法,这比其他方法要快。
答案 1 :(得分:0)
我们可以使用std:generate()
来实现:
#include <bits/stdc++.h>
using namespace std;
vector <string> strVector{ "hello", "world" };
vector <int> intVector{ 2, 3 };
pair<string, int> f()
{
static int i = -1;
++i;
return make_pair(strVector[i], intVector[i]);
}
int main() {
int min_Size = min(strVector.size(), intVector.size());
vector< pair<string,int> > pairVector(min_Size);
generate(pairVector.begin(), pairVector.end(), f);
for( int i = 0 ; i < 2 ; i++ )
cout << pairVector[i].first <<" " << pairVector[i].second << endl;
}
答案 2 :(得分:0)
我将根据您的情况尝试总结您的需求,并给出一些可能的答案。您说您想要一个新的向量,该向量实际上是包含两个异构类型的其他两个向量的压缩版本。在哪里可以以某种配对的方式访问这两种类型?
如果要提高效率,您需要考虑将新向量用于什么目的?我可以看到三种您正在做的情况。
1)除了将数据复制到新向量中之外,您无能为力。在Sam Varshavchik的答案中作了更多解释。
3)您执行类似Shakil的答案或here或某种类型的自定义迭代器的操作。
2)在此处进行一些优化,在其中使用包装器类对数据进行零处理。 注意:如果您不需要使用实际的std :: vector
class StringIntContainer {
public:
StringIntContaint(std::vector<std::string>& _string_vec, std::vector<int>& _int_vec)
: string_vec_(std::move(_string_vec)), int_vec_(std::move(_int_vec))
{
assert(string_vec_.size() == int_vec_.size());
}
std::pair<std::string, int> operator[] (std::size_t _i) const
{
return std::make_pair(string_vec_[_i], int_vec_[_i]);
}
/* You may want methods that return reference to data so you can edit it*/
std::pair<std::vector<std::string>, std::vector<int>> Decompose()
{
return std::make_pair(std::move(string_vec_), std::move(int_vec_[_i])));
}
private:
std::vector<std::string> _string_vec_;
std::vector<int> int_vec_;
};