将std :: vector的副本附加到自身的末尾

时间:2014-02-15 19:49:32

标签: c++ gcc iterator clang llvm

我正在尝试制作一个字符串向量的副本,并将其附加到其原始向量的末尾,即复制其内容。例如:

 Input : vector<string> s = {"abc", "def"}
 Output: vector<string> s = {"abc", "def", "abc", "def"}

我使用的是插入方法,即

s.insert(s.end(), s.begin(), s.end());

然而,这表现出与编译器相关的结果。在,LLVM clang,它给了我预期的答案。

GCC给了我

 Output: vector<string> s = {"abc", "def", "", ""}

我想知道为什么会发生这种情况以及实现此向量重复目标最安全的方法是什么?

以下是上述程序的ideone.com链接:http://ideone.com/40CH8q

4 个答案:

答案 0 :(得分:5)

尽管可以使用迭代器完成,但安全的替代方法是避免它们:

size_t size = v.size();  // Of course we shouldn't access .size() in the loop...
v.reserve(size * 2);     // Preallocation. Thanks @Ali for this performance hint
for (size_t i = 0; i < size; ++i)
    v.push_back(v[i]);

通常,使用迭代器同时修改数据结构(不仅仅是其元素)是危险的;当迭代器失效时以及在修改后重用旧迭代器是安全的时候,你应该仔细阅读。因此,有时使用“旧”方法迭代随机访问序列是有意义的:使用索引变量。

答案 1 :(得分:3)

正如其他人已经指出的那样,你需要通过调用vector::reserve()来确保在插入过程中不会重新分配向量。 (如果您选择将带有push_back()的元素放入向量中,则调用reserve也是一个好主意。)

然后仍然存在迭代器失效问题(详见vector::insert()),但据我所知,下面的代码绕过了:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>

using namespace std;

int main() {

  vector<string> s{"abc", "def"};

  auto size = s.size();

  s.reserve(2*size); // <-- This one is essential to ensure
                     //     no reallocation during insertion

  const string* first = s.data(); // using pointer, instead of iterator

  copy(first, first+size, back_inserter(s));

  for (const auto& e : s)
    cout << e << '\t';

  cout << endl;
}

答案 2 :(得分:0)

如前所述,您需要做的就是拨打reserve

sv.reserve(sv.size() * 2);

这是因为如果发生重新分配,迭代器将失效。你可以自己检查一下:

std::cout << sv.capacity() << "\n"; // 2

新尺寸将大于容量,因此会重新分配。

答案 3 :(得分:0)

这也可以这样做

vector<string> data = {"abc", "def"}; // Input String Vector
int len = data.size();
for(int i = 0; i < len; i++)
{
    data.push_back(data[i]); // Making Copy of String Vector
}

vector<string> data = {"abc", "def", "abc", "def"};
//Resultant String Vector
相关问题