如何在没有循环的情况下将数组的内容复制到C ++中的std :: vector?

时间:2008-11-03 17:03:46

标签: c++ stl vector copy

我有一个值数组,这些值从我需要存储的程序的不同部分传递给我的函数,以便以后处理。由于我不知道在处理数据之前我的函数会被调用多少次,所以我需要一个动态存储结构,所以我选择了std::vector。我不想单独对push_back所有值进行标准循环,如果我可以使用与memcpy类似的东西复制它,那就太好了。

10 个答案:

答案 0 :(得分:185)

这里有很多答案,几乎所有答案都可以完成工作。

然而,有一些误导性建议!

以下是选项:

vector<int> dataVec;

int dataArray[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
unsigned dataArraySize = sizeof(dataArray) / sizeof(int);

// Method 1: Copy the array to the vector using back_inserter.
{
    copy(&dataArray[0], &dataArray[dataArraySize], back_inserter(dataVec));
}

// Method 2: Same as 1 but pre-extend the vector by the size of the array using reserve
{
    dataVec.reserve(dataVec.size() + dataArraySize);
    copy(&dataArray[0], &dataArray[dataArraySize], back_inserter(dataVec));
}

// Method 3: Memcpy
{
    dataVec.resize(dataVec.size() + dataArraySize);
    memcpy(&dataVec[dataVec.size() - dataArraySize], &dataArray[0], dataArraySize * sizeof(int));
}

// Method 4: vector::insert
{
    dataVec.insert(dataVec.end(), &dataArray[0], &dataArray[dataArraySize]);
}

// Method 5: vector + vector
{
    vector<int> dataVec2(&dataArray[0], &dataArray[dataArraySize]);
    dataVec.insert(dataVec.end(), dataVec2.begin(), dataVec2.end());
}

简而言之,使用vector :: insert,方法4最适合bsruth的场景。

以下是一些血腥的细节:

方法1 可能是最容易理解的。只需从数组中复制每个元素并将其推入向量的背面即可。唉,这很慢。因为有一个循环(隐含了复制功能),所以必须单独处理每个元素;基于我们知道数组和向量是连续块的事实,不能进行性能改进。

方法2 是对方法1的建议性能改进;在添加之前预先保留数组的大小。对于大型阵列,此可能有帮助。但是,这里最好的建议是永远不要使用reserve,除非分析表明你可以得到改进(或者你需要确保你的迭代器不会失效)。 Bjarne agrees。顺便说一句,我发现这个方法大部分时间都执行了最慢,虽然我正在努力全面解释为什么它常常显着比方法1慢......

方法3 是旧学校的解决方案 - 在问题上抛出一些C!对于POD类型,工作正常且快速。在这种情况下,需要调用resize,因为memcpy在向量的边界之外工作,并且无法告诉向量它的大小已经改变。除了是一个丑陋的解决方案(字节复制!),请记住,只能用于POD类型。我永远不会使用这个解决方案。

方法4 是最好的方法。它的意思很明确,它(通常)最快,适用于任何物体。将此方法用于此应用程序没有任何缺点。

方法5 是对方法4的调整 - 将数组复制到向量中然后追加它。好的选择 - 通常快速且清晰。

最后,您知道可以使用向量代替数组,对吧?即使函数需要c样式数组,也可以使用向量:

vector<char> v(50); // Ensure there's enough space
strcpy(&v[0], "prefer vectors to c arrays");

希望帮助那里的人!

答案 1 :(得分:96)

如果你可以在获得数组和数组大小后构造向量,你可以说:

std::vector<ValueType> vec(a, a + n);

...假设a是您的数组,n是它包含的元素数。否则,std::copy() w / resize()就可以了。

除非您确定这些值是普通数据(POD)类型,否则我将远离memcpy()

另外,值得注意的是,这些都没有真正避免for循环 - 这只是一个问题,你是否必须在你的代码中看到它。复制值时,O(n)运行时性能是不可避免的。

最后,请注意,对于大多数STL算法,C样式数组是完全有效的容器 - 原始指针等同于begin(),而(ptr + n)等同于end()

答案 2 :(得分:28)

如果您所做的只是替换现有数据,那么您可以这样做

std::vector<int> data; // evil global :)

void CopyData(int *newData, size_t count)
{
   data.assign(newData, newData + count);
}

答案 3 :(得分:11)

std::copy正是您要找的。

答案 4 :(得分:4)

由于我只能编辑自己的答案,因此我将根据我的问题的其他答案做出综合答案。感谢所有回答的人。

使用std::copy,这仍然在后台迭代,但您不必输入代码。

int foo(int* data, int size)
{
   static std::vector<int> my_data; //normally a class variable
   std::copy(data, data + size, std::back_inserter(my_data));
   return 0;
}

使用常规memcpy。这可能最适用于基本数据类型(即int),但不适用于更复杂的结构或类数组。

vector<int> x(size);
memcpy(&x[0], source, size*sizeof(int));

答案 5 :(得分:4)

int dataArray[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };//source

unsigned dataArraySize = sizeof(dataArray) / sizeof(int);

std::vector<int> myvector (dataArraySize );//target

std::copy ( myints, myints+dataArraySize , myvector.begin() );

//myvector now has 1,2,3,...10 :-)

答案 6 :(得分:3)

我说,避免使用memcpy。除非你真的需要,否则没有理由搞乱指针操作。此外,它仅适用于POD类型(如int),但如果您正在处理需要构造的类型,则会失败。

答案 7 :(得分:1)

除了上面介绍的方法之外,还需要确保使用std :: Vector.reserve(),std :: Vector.resize(),或者构造向量大小,以确保向量具有其中包含足够的元素来保存您的数据。如果没有,你会破坏记忆。对于std :: copy()或memcpy()都是如此。

这是使用vector.push_back()的原因,你无法写出过去的向量结尾。

答案 8 :(得分:1)

另一个答案,因为这个人说“我不知道我的函数会被调用多少次”,你可以使用像这样的向量插入方法将值数组附加到向量的末尾:

vector<int> x;

void AddValues(int* values, size_t size)
{
   x.insert(x.end(), values, values+size);
}

我喜欢这种方式,因为向量的实现应该能够优化以根据迭代器类型和类型本身插入值的最佳方式。您在某种程度上回复了stl。

的实现

如果您需要保证最快的速度,并且您知道您的类型是POD类型,那么我会在Thomas的答案中推荐调整大小的方法:

vector<int> x;

void AddValues(int* values, size_t size)
{
   size_t old_size(x.size());
   x.resize(old_size + size, 0);
   memcpy(&x[old_size], values, size * sizeof(int));
}

答案 9 :(得分:0)

假设您知道向量中的项目有多大:

std::vector<int> myArray;
myArray.resize (item_count, 0);
memcpy (&myArray.front(), source, item_count * sizeof(int));

http://www.cppreference.com/wiki/stl/vector/start