当前位置:   article > 正文

c++ vector容器 创建动态数组及拷贝优化_vector添加元素时会创建一个新数组并拷贝吗

vector添加元素时会创建一个新数组并拷贝吗

vector包含在c++标准模版库中,能够存放任意类型的动态数组,类似于一个容器,能够增加数据和减少数据

使用方法如下:

  1. #include <iostream>
  2. #include <vector>
  3. struct Vertex{
  4. int x,y,z;
  5. Vertex(int a, int b, int c)
  6. : x(a), y(b),z(c){}
  7. };
  8. std::ostream& operator<<(std::ostream& stream, const Vertex& vertex){
  9. stream << vertex.x << "," << vertex.y << "," << vertex.z;
  10. return stream;
  11. }
  12. int main(){
  13. std::vector<Vertex> vertices;
  14. Vertex v1(1,2,3);
  15. Vertex v2(4,5,6);
  16. vertices.push_back(v1);
  17. vertices.push_back(v2);
  18. for(int i = 0; i< vertices.size(); i++){
  19. std::cout << vertices[i] <<std::endl;
  20. }
  21. vertices.erase(vertices.begin() +1);
  22. for(Vertex& v : vertices){
  23. std::cout << v << std::endl;
  24. }
  25. std::cin.get();
  26. }

1. #include <vector> 声明头文件

2. std::vector<Vertex> vertices; 创建动态数组(数组类型为Vertex)

3. vertices.push_back(v1); 将Vertex类型的变量v1加入数组

4. vertices.erase(vertices.begin() +1); 删除第二个位置的值

当往vector数组添加元素时,会发生多次没必要的拷贝,降低代码效率,如下:

  1. #include <iostream>
  2. #include <vector>
  3. struct Vertex{
  4. int x,y,z;
  5. Vertex(int a, int b, int c)
  6. : x(a), y(b),z(c){}
  7. Vertex(const Vertex& vertex)
  8. :x(vertex.x), y(vertex.y), z(vertex.z){
  9. std::cout << "copy" << std::endl;
  10. }
  11. };
  12. std::ostream& operator<<(std::ostream& stream, const Vertex& vertex){
  13. stream << vertex.x << "," << vertex.y << "," << vertex.z;
  14. return stream;
  15. }
  16. int main(){
  17. std::vector<Vertex> vertices;
  18. Vertex v1(1,2,3);
  19. Vertex v2(4,5,6);
  20. Vertex v3(4,5,6);
  21. vertices.push_back(v1);
  22. vertices.push_back(v2);
  23. vertices.push_back(v3);
  24. std::cin.get();
  25. }

当动态数组创建时,因为没有包含元素,所以不占用内存。当需要push元素进数组时,系统会调整数组长度为1,然后拷贝该元素到数组。当再次push第二个元素时,系统会调整数组长度为2,而且会指定一个新的内存地址,然后把两个元素都拷贝过去。这就降低了效率。同理,第三个元素时,拷贝次数到了6次。

  1. $ ./a.out
  2. copy
  3. copy
  4. copy
  5. copy
  6. copy
  7. copy

为了应对该问题,分两步:

1. 先为该数组预留长度,这样只要数组实际长度没达到这个值,就不会发生上述现象。代码如下:

vertices.reserve(3);  
  1. #include <iostream>
  2. #include <vector>
  3. struct Vertex{
  4. int x,y,z;
  5. Vertex(int a, int b, int c)
  6. : x(a), y(b),z(c){}
  7. Vertex(const Vertex& vertex)
  8. :x(vertex.x), y(vertex.y), z(vertex.z){
  9. std::cout << "copy" << std::endl;
  10. }
  11. };
  12. std::ostream& operator<<(std::ostream& stream, const Vertex& vertex){
  13. stream << vertex.x << "," << vertex.y << "," << vertex.z;
  14. return stream;
  15. }
  16. int main(){
  17. std::vector<Vertex> vertices;
  18. vertices.reserve(3);
  19. Vertex v1(1,2,3);
  20. Vertex v2(4,5,6);
  21. Vertex v3(4,5,6);
  22. vertices.push_back(v1);
  23. vertices.push_back(v2);
  24. vertices.push_back(v3);
  25. std::cin.get();
  26. }

运行结果显示,只发生了三次拷贝

  1. $ ./a.out
  2. copy
  3. copy
  4. copy

2. 进一步优化,即不在main函数中创建元素再拷贝到数组,而是直接在预留的内存地址生成,代码如下

  1. vertices.emplace_back(1,2,3);
  2. vertices.emplace_back(4,5,6);
  3. vertices.emplace_back(7,8,9);
  1. #include <iostream>
  2. #include <vector>
  3. struct Vertex{
  4. int x,y,z;
  5. Vertex(int a, int b, int c)
  6. : x(a), y(b),z(c){}
  7. Vertex(const Vertex& vertex)
  8. :x(vertex.x), y(vertex.y), z(vertex.z){
  9. std::cout << "copy" << std::endl;
  10. }
  11. };
  12. std::ostream& operator<<(std::ostream& stream, const Vertex& vertex){
  13. stream << vertex.x << "," << vertex.y << "," << vertex.z;
  14. return stream;
  15. }
  16. int main(){
  17. std::vector<Vertex> vertices;
  18. vertices.reserve(3);
  19. // Vertex v1(1,2,3);
  20. // Vertex v2(4,5,6);
  21. // Vertex v3(4,5,6);
  22. // vertices.push_back(v1);
  23. // vertices.push_back(v2);
  24. // vertices.push_back(v3);
  25. vertices.emplace_back(1,2,3);
  26. vertices.emplace_back(4,5,6);
  27. vertices.emplace_back(7,8,9);
  28. std::cin.get();
  29. }

运行结果显示一次拷贝也没有发生。

注意在mac上编译时,如果使用xcode工具链的编译工具,会报错

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号