将向量元素复制到向量对

时间:2019-03-02 01:33:17

标签: 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个向量的元素添加到向量对中。我怀疑这是一种有效的方法,因为此函数被称为传递不同数据的时间的数百倍。这可能会导致性能问题,因为它每次都经过循环。

我的目标是将“ 一遍 ”中的两个向量都复制到向量对中。即不使用循环。不知道这是否有可能。

在不影响性能的情况下,还有更好的方法吗?

3 个答案:

答案 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. 新矢量是数据的副本,因此您可以在不影响原始矢量的情况下进行处理。 (我仍然需要原始的两个向量)
  2. 新的向量现在是数据的存储机制。 (ei you 不再需要原始的两个向量)
  3. 您只需将向量耦合在一起即可简化使用和表示。 (ei的存储位置实际上并不重要)

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_;

};
相关问题