140

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

4

10 回答 10

238

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

但是有一些误导性的建议!

以下是选项:

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());
}

长话短说,方法 4 使用 vector::insert 是 bsruth 场景的最佳选择。

以下是一些血腥的细节:

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

方法 2是对方法 1 的建议性能改进;只需在添加之前预先保留数组的大小。对于大型阵列,这可能会有所帮助。然而,这里最好的建议是永远不要使用保留,除非分析表明您可以得到改进(或者您需要确保您的迭代器不会失效)。 Bjarne 同意。顺便说一句,我发现这种方法在大多数情况下执行得最慢,尽管我正在努力全面解释为什么它通常比方法 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");

希望能帮助那里的人!

于 2008-11-04T11:42:17.700 回答
134

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

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

...假设a是您的数组,并且n是它包含的元素数。否则,std::copy()w/resize()会成功的。

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

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

最后,请注意,对于大多数 STL 算法来说,C 风格的数组是完全有效的容器——原始指针等价于begin(),并且 ( ptr + n) 等价于end().

于 2008-11-03T17:38:36.653 回答
45

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

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

void CopyData(int *newData, size_t count)
{
   data.assign(newData, newData + count);
}
于 2008-11-03T17:39:26.433 回答
12

std::copy是您正在寻找的。

于 2008-11-03T17:07:34.283 回答
12

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

使用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));
于 2008-11-03T17:08:18.573 回答
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 :-)
于 2017-03-01T14:56:57.513 回答
2

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

于 2008-11-03T17:17:55.543 回答
2

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

vector<int> x;

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

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

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

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));
}
于 2008-11-03T18:56:15.047 回答
1

除了上面介绍的方法之外,您还需要确保使用 std::Vector.reserve()、std::Vector.resize() 或根据大小构造向量,以确保向量中有足够的元素它来保存你的数据。否则,您将破坏内存。对于 std::copy() 或 memcpy() 都是如此。

这就是使用vector.push_back() 的原因,你不能写超出向量的末尾。

于 2008-11-03T17:29:02.663 回答
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

于 2008-11-03T17:09:15.077 回答