当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何在没有循环的情况下将数组的内容复制到C++中的std::vector?》经验,为你挑选了6个好方法。

我有一个值数组,从程序的不同部分传递给我的函数,我需要存储以供以后处理.因为我不知道有多少次之前,它是时间来处理数据我函数将被调用做什么,我需要一个动态的存储结构,所以我选择了一个std::vector.我不想push_back单独对所有值进行标准循环,如果我可以使用类似的东西复制它,那将是很好的memcpy.



1> MattyT..:

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

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

以下是选项:

vector 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 dataVec2(&dataArray[0], &dataArray[dataArraySize]);
    dataVec.insert(dataVec.end(), dataVec2.begin(), dataVec2.end());
}

简而言之,方法4,使用vector :: insert,对于bsruth的场景是最好的.

这里有一些血腥的细节:

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

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

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

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

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

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

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

希望能帮到那里的人!


你不能安全地和可移植地引用"&dataArray [dataArraySize]" - 它取消引用一个过去的结束指针/迭代器.相反,你可以说dataArray + dataArraySize来获取指针而不必先取消引用它.
@Drew:是的,你可以,至少在C.中定义`&expr`不评估`expr`,它只计算它的地址.并且指针*一个*超过最后一个元素也是完全有效的.
你有没有尝试用2做方法4?即在插入之前保留空间.似乎如果数据大小很大,多次插入将需要多次重新分配.因为我们知道先验的大小,我们可以在插入之前进行重新分配.

2> Drew Hall..:

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

std::vector vec(a, a + n);

...假设a是你的数组,它n是它包含的元素数.否则,std::copy()w/resize()会做的伎俩.

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

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

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


无法构造的另一种选择是[assign](http://stackoverflow.com/questions/259297/):`vec.assign(a,a + n)`,它比复制和调整大小更紧凑.
循环和调用push_back错误的原因是因为如果数组足够长,您可能会强制向量多次调整大小.
@bradtgmurray:即使push_back()也不会太糟糕,因为向量的指数增长(又称"摊销的常数时间").我认为在最坏的情况下,运行时间只会是2倍.
如果向量已经存在,则为vec.clear();。vec.insert(vec.begin(),a,a + n); 也会工作。然后,您甚至不需要将a用作指针,只需一个迭代器,并且向量分配将是通用的故障转移(以及C ++ / STL方式)。

3> Torlack..:

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

std::vector data; // evil global :)

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



4> luke..:

std :: copy就是你要找的东西.



5> bsruth..:

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

使用std :: copy,它仍然在后台进行迭代,但是您不必键入代码。

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

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

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



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

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

std::vector myvector (dataArraySize );//target

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

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

推荐阅读
yzh148448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有