如何在不循环的情况下将数组的内容复制到 C++ 中的 std::vector?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/259297/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you copy the contents of an array to a std::vector in C++ without looping?
提问by bsruth
I have an array of values that is passed to my function from a different part of the program that I need to store for later processing. Since I don't know how many times my function will be called before it is time to process the data, I need a dynamic storage structure, so I chose a std::vector
. I don't want to have to do the standard loop to push_back
all the values individually, it would be nice if I could just copy it all using something similar to memcpy
.
我有一个值数组,这些值从程序的不同部分传递给我的函数,我需要存储这些值以供以后处理。由于我不知道在处理数据之前我的函数会被调用多少次,我需要一个动态的存储结构,所以我选择了一个std::vector
. 我不想对push_back
所有值单独执行标准循环,如果我可以使用类似于memcpy
.
采纳答案by Drew Hall
If you can construct the vector after you've gotten the array and array size, you can just say:
如果在获得数组和数组大小后可以构造向量,则可以说:
std::vector<ValueType> vec(a, a + n);
...assuming a
is your array and n
is the number of elements it contains. Otherwise, std::copy()
w/resize()
will do the trick.
...假设a
是你的数组,n
是它包含的元素数。否则,std::copy()
w/resize()
将起作用。
I'd stay away from memcpy()
unless you can be sure that the values are plain-old data (POD) types.
memcpy()
除非您可以确定这些值是普通数据 (POD) 类型,否则我会远离。
Also, worth noting that none of these really avoids the for loop--it's just a question of whether you have to see it in your code or not. O(n) runtime performance is unavoidable for copying the values.
另外,值得注意的是,这些都没有真正避免 for 循环——这只是您是否必须在代码中看到它的问题。O(n) 运行时性能对于复制值是不可避免的。
Finally, note that C-style arrays are perfectly valid containers for most STL algorithms--the raw pointer is equivalent to begin()
, and (ptr + n
) is equivalent to end()
.
最后,请注意,对于大多数 STL 算法而言,C 样式数组是完全有效的容器——原始指针等效于begin()
,并且 ( ptr + n
) 等效于end()
。
回答by MattyT
There have been many answers here and just about all of them will get the job done.
这里有很多答案,几乎所有答案都能完成。
However there is some misleading advice!
然而,有一些误导性的建议!
Here are the options:
以下是选项:
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());
}
To cut a long story short Method 4, using vector::insert, is the best for bsruth's scenario.
长话短说,使用 vector::insert 的方法 4 最适合 bsruth 的场景。
Here are some gory details:
以下是一些血腥的细节:
Method 1is probably the easiest to understand. Just copy each element from the array and push it into the back of the vector. Alas, it's slow. Because there's a loop (implied with the copy function), each element must be treated individually; no performance improvements can be made based on the fact that we know the array and vectors are contiguous blocks.
方法 1可能是最容易理解的。只需从数组中复制每个元素并将其推入向量的后面。唉,这很慢。因为有一个循环(隐含在复制函数中),每个元素都必须单独处理;基于我们知道数组和向量是连续块这一事实,无法提高性能。
Method 2is a suggested performance improvement to Method 1; just pre-reserve the size of the array before adding it. For large arrays this mighthelp. However the best advice here is never to use reserve unless profiling suggests you may be able to get an improvement (or you need to ensure your iterators are not going to be invalidated). Bjarne agrees. Incidentally, I found that this method performed the slowestmost of the time though I'm struggling to comprehensively explain why it was regularly significantlyslower than method 1...
方法 2是对方法 1 的建议性能改进;只需在添加数组之前预先保留数组的大小。对于大型阵列,这可能会有所帮助。然而,这里最好的建议是永远不要使用保留,除非分析表明您可能能够获得改进(或者您需要确保您的迭代器不会失效)。 Bjarne 同意。顺便说一句,我发现这个方法执行的最慢的大部分时间,虽然我竭力要全面地解释为什么它是定期显著慢于法1 ...
Method 3is the old school solution - throw some C at the problem! Works fine and fast for POD types. In this case resize is required to be called since memcpy works outside the bounds of vector and there is no way to tell a vector that its size has changed. Apart from being an ugly solution (byte copying!) remember that this can only be used for POD types. I would never use this solution.
方法 3是老派的解决方案 - 在问题上扔一些 C!对于 POD 类型,工作正常且快速。在这种情况下,需要调用 resize,因为 memcpy 在向量范围之外工作,并且无法告诉向量其大小已更改。除了是一个丑陋的解决方案(字节复制!)请记住,这只能用于 POD 类型。我永远不会使用这个解决方案。
Method 4is the best way to go. It's meaning is clear, it's (usually) the fastest and it works for any objects. There is no downside to using this method for this application.
方法 4是最好的方法。它的含义很明确,它(通常)是最快的,并且适用于任何对象。将此方法用于此应用程序没有任何缺点。
Method 5is a tweak on Method 4 - copy the array into a vector and then append it. Good option - generally fast-ish and clear.
方法 5是对方法 4 的调整 - 将数组复制到向量中,然后附加它。不错的选择 - 通常是快速和清晰的。
Finally, you are aware that you can use vectors in place of arrays, right? Even when a function expects c-style arrays you can use vectors:
最后,您知道可以使用向量代替数组,对吗?即使函数需要 c 样式数组,您也可以使用向量:
vector<char> v(50); // Ensure there's enough space
strcpy(&v[0], "prefer vectors to c arrays");
Hope that helps someone out there!
希望能帮助到那里的人!
回答by Torlack
If all you are doing is replacing the existing data, then you can do this
如果您所做的只是替换现有数据,那么您可以这样做
std::vector<int> data; // evil global :)
void CopyData(int *newData, size_t count)
{
data.assign(newData, newData + count);
}
回答by bsruth
Since I can only edit my own answer, I'm going to make a composite answer from the other answers to my question. Thanks to all of you who answered.
由于我只能编辑自己的答案,因此我将根据我的问题的其他答案做出综合答案。感谢所有回答的人。
Using std::copy, this still iterates in the background, but you don't have to type out the code.
使用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;
}
Using regular memcpy. This is probably best used for basic data types (i.e. int) but not for more complex arrays of structs or classes.
使用常规memcpy。这可能最适用于基本数据类型(即 int),但不适用于更复杂的结构或类数组。
vector<int> x(size);
memcpy(&x[0], source, size*sizeof(int));
回答by Antonio Ramasco
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 :-)
回答by Assaf Lavie
avoid the memcpy, I say. No reason to mess with pointer operations unless you really have to. Also, it will only work for POD types (like int) but would fail if you're dealing with types that require construction.
避免使用 memcpy,我说。没有理由搞乱指针操作,除非你真的必须这样做。此外,它仅适用于 POD 类型(如 int),但如果您正在处理需要构造的类型,则会失败。
回答by Shane Powell
Yet another answer, since the person said "I don't know how many times my function will be called", you could use the vector insert method like so to append arrays of values to the end of the vector:
还有一个答案,因为这个人说“我不知道我的函数会被调用多少次”,你可以像这样使用向量插入方法将值数组附加到向量的末尾:
vector<int> x;
void AddValues(int* values, size_t size)
{
x.insert(x.end(), values, values+size);
}
I like this way because the implementation of the vector should be able to optimize for the best way to insert the values based on the iterator type and the type itself. You are somewhat replying on the implementation of stl.
我喜欢这种方式,因为向量的实现应该能够优化基于迭代器类型和类型本身插入值的最佳方式。你有点回复stl的实现。
If you need to guarantee the fastest speed and you know your type is a POD type then I would recommend the resize method in Thomas's answer:
如果您需要保证最快的速度并且您知道您的类型是 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));
}
回答by Thomas Jones-Low
In addition to the methods presented above, you need to make sure you use either std::Vector.reserve(), std::Vector.resize(), or construct the vector to size, to make sure your vector has enough elements in it to hold your data. if not, you will corrupt memory. This is true of either std::copy() or memcpy().
除了上面介绍的方法之外,您还需要确保使用 std::Vector.reserve()、std::Vector.resize() 或将向量构造为大小,以确保向量中有足够的元素它来保存您的数据。否则,您将破坏内存。std::copy() 或 memcpy() 都是如此。
This is the reason to use vector.push_back(), you can't write past the end of the vector.
这就是使用 vector.push_back() 的原因,你不能写越过向量的末尾。
回答by Thomas Jones-Low
Assuming you know how big the item in the vector are:
假设您知道向量中的项目有多大:
std::vector<int> myArray;
myArray.resize (item_count, 0);
memcpy (&myArray.front(), source, item_count * sizeof(int));