如何在没有循环的情况下将数组的内容复制到C ++中的std :: vector?
题
我有一个值数组,这些值从我需要存储的程序的不同部分传递给我的函数,以便以后处理。由于我不知道在处理数据之前我的函数会被调用多少次,所以我需要一个动态存储结构,所以我选择了 std :: vector
。我不想单独对 push_back
所有值进行标准循环,如果我可以使用类似于 memcpy
的东西来复制它,那就太好了。
解决方案
如果你可以在获得数组和数组大小后构造向量,你可以说:
std::vector<ValueType> vec(a, a + n);
...假设 a
是你的数组而 n
是它包含的元素数。否则, std :: copy()
w / resize()
就可以了。
除非您确定这些值是普通旧数据(POD)类型,否则我将远离 memcpy()
。
另外,值得注意的是,这些都没有真正避免for循环 - 这只是一个问题,你是否必须在你的代码中看到它。复制值时,O(n)运行时性能是不可避免的。
最后,请注意,C风格的数组对于大多数STL算法来说都是完全有效的容器 - 原始指针等同于 begin()
和( ptr + n
)相当于 end()
。
其他提示
这里有很多答案,几乎所有答案都可以完成工作。
然而,有一些误导性建议!
以下是选项:
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同意。顺便说一句,我发现这个方法大部分时间执行最慢虽然我正在努力全面解释为什么它常常显着比方法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");
希望帮助那里的人!
如果您所做的只是替换现有数据,那么您可以这样做
std::vector<int> data; // evil global :)
void CopyData(int *newData, size_t count)
{
data.assign(newData, newData + count);
}
std :: copy 正是您所需要的。
由于我只能编辑自己的答案,因此我将根据我的问题的其他答案做出综合答案。感谢所有回答的人。
使用 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));
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 :-)
除了上面介绍的方法之外,还需要确保使用std :: Vector.reserve(),std :: Vector.resize(),或者构造向量大小,以确保向量具有其中包含足够的元素来保存您的数据。如果没有,你会破坏记忆。对于std :: copy()或memcpy()都是如此。
这是使用vector.push_back()的原因,你无法写出过去的向量结尾。
另一个答案,因为这个人说“我不知道我的函数会被调用多少次”,你可以使用像这样的向量插入方法将值数组附加到向量的末尾: / p>
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));
}
假设您知道向量中的项目有多大:
std::vector<int> myArray;
myArray.resize (item_count, 0);
memcpy (&myArray.front(), source, item_count * sizeof(int));