如何将数组的内容复制到 C++ 中的 std::vector 不循环?

发布于 2024-07-07 23:24:24 字数 210 浏览 6 评论 0原文

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

鸵鸟症 2024-07-14 23:24:24

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

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

以下是选项:

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");

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.

Here are some gory details:

Method 1 is 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.

Method 2 is a suggested performance improvement to Method 1; just pre-reserve the size of the array before adding it. For large arrays this might help. 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 slowest most of the time though I'm struggling to comprehensively explain why it was regularly significantly slower than method 1...

Method 3 is 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.

Method 4 is 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.

Method 5 is a tweak on Method 4 - copy the array into a vector and then append it. Good option - generally fast-ish and clear.

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:

vector<char> v(50); // Ensure there's enough space
strcpy(&v[0], "prefer vectors to c arrays");
风启觞 2024-07-14 23:24:24

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

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

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

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

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

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

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.

I'd stay away from memcpy() unless you can be sure that the values are plain-old data (POD) types.

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.

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().

七禾 2024-07-14 23:24:24

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

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

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

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);
}
差↓一点笑了 2024-07-14 23:24:24

std::copy 就是您要寻找的。

std::copy is what you're looking for.

憧憬巴黎街头的黎明 2024-07-14 23:24:24

由于我只能编辑自己的答案,因此我将从我的问题的其他答案中得出一个综合答案。 感谢所有回答的人。

使用 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));

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.

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.

vector<int> x(size);
memcpy(&x[0], source, size*sizeof(int));
爱你是孤单的心事 2024-07-14 23:24:24

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

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

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.

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:

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));
}
微暖i 2024-07-14 23:24:24
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 :-)
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 :-)
删除会话 2024-07-14 23:24:24

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

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.

感情洁癖 2024-07-14 23:24:24

除了上面介绍的方法之外,您还需要确保使用 std::Vector.reserve()、std::Vector.resize() 或构造符合大小的向量,以确保向量中有足够的元素它来保存您的数据。 如果不这样做,你就会破坏记忆。 std::copy() 或 memcpy() 都是如此。

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

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().

This is the reason to use vector.push_back(), you can't write past the end of the vector.

爱*していゐ 2024-07-14 23:24:24

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

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

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文