C++的vector使用优化

打印 上一主题 下一主题

主题 674|帖子 674|积分 2022

我们在上一章说了怎样使用这个vector动态数组,这章我们说说怎样更好的使用它以及它是怎样工作的。当你创建一个vector,然后使用push_back添加元素,当当前的vector的内存不够时,会从内存中的旧位置复制到内存中的新位置,然后删除删除旧位置的内存,也就是说当我push_back,vector容量不够添加元素就会调整巨细,重新分配,这也就是将代码拖慢的原因之一。是事实,我们必要不停的重新分配,这是一个非常迟钝的操作,应该制止。我们怎样制止复制对象,如果我们处理的是vector,特别是基于vector的对象,我们没有存储vector指针,我们存储的是vector对象,那占的内存就更大了,所以我们要优化复制。
  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. struct Vertex
  5. {
  6.         float x, y, z;
  7.         Vertex(float x, float y, float z)
  8.                 : x(x), y(y), z(z)
  9.         {
  10.                
  11.         }
  12.         //拷贝构造
  13.         Vertex(const Vertex& vertex)
  14.                 : x(vertex.x), y(vertex.y), z(vertex.z)
  15.         {
  16.                 std::cout << "Copied!" << std::endl;
  17.         }
  18. };
  19. int main()
  20. {
  21.         std::vector<Vertex> vertices;
  22.     //打印6次
  23.         //vertices.push_back(Vertex(1, 2, 3));
  24.         //vertices.push_back(Vertex(4, 8, 9));
  25.         //vertices.push_back(Vertex(7, 5, 6));
  26.     //打印3次
  27.         vertices.reserve(3);
  28.         vertices.push_back(Vertex(1, 2, 3));
  29.         vertices.push_back(Vertex(4, 8, 9));
  30.         vertices.push_back(Vertex(7, 5, 6));
  31.         std::cin.get();
  32.     //打印0次
  33.     vertices.emplace_back(1, 2, 3);
  34.         vertices.emplace_back(14, 4, 6);
  35.         vertices.emplace_back(7, 8, 9);
  36. }
复制代码


在上面这段代码中,我们复制了6次(调用了6次拷贝构造函数),这个是为什么呢?当我们在push_back的时候,我们现实是在,主函数的当前帧中构造它,所以我们在main的栈上创建它,然后我们必要做的是,把它放到这个vector中,所以我们是从main函数中(把这个创建的vertex)放到现实的vector中。
在 C++ 中,std::vector 是一个动态数组,它可以调整其巨细以容纳不同数量的元素。当你调用 reserve 方法时,你告诉 vector 它应该预先分配充足的内存来存储指定命量的元素,但并不会真正添加这些元素。如许做的好处是,当你稍后添加元素到 vector 时,它大概不必要重新分配内存(如果添加的元素数量没有超过预留的数量),这可以进步服从,由于内存分配通常是一个昂贵的操作。
在我们的代码中,由于预留了 3 个元素的空间,因此当你添加前三个元素时,不必要重新分配内存,所以不会调用拷贝构造函数(除了大概的隐式移动构造函数或复制省略,但这些在这个例子中都不适用,由于直接传递了临时对象)。但是,如果你没有调用 reserve,并且 vector 的初始容量小于你要添加的元素数量,那么在添加元素时大概必要重新分配内存。在重新分配内存时,旧的元素会被拷贝(或移动)到新的内存位置,这就会调用拷贝构造函数(或移动构造函数)。
当你使用 vertices.emplace_back(1, 2, 3);(以及类似的 emplace_back 调用)时,你现实上是在告诉 std::vector 直接在其内部存储中构造 Vertex 对象,而不是先创建一个临时对象然后再将其拷贝或移动到 vector 中。这是 emplace_back 相较于 push_back 的主要优势之一,由于它制止了不必要的拷贝或移动操作,从而进步了服从。
由于 emplace_back 直接在 vector 的内存中构造对象,它不会调用 Vertex 的拷贝构造函数。相反,它会调用 Vertex 的构造函数,直接传递参数给构造函数来构造对象。这就是为什么你在使用 emplace_back 后没有看到 "Copied!" 的输出。而是三次Constructed!
  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. struct Vertex
  5. {
  6.         float x, y, z;
  7.         Vertex(float x, float y, float z)
  8.                 : x(x), y(y), z(z)
  9.         {
  10.                 std::cout << "Constructed!" << std::endl;
  11.         }
  12.         //拷贝构造
  13.         Vertex(const Vertex& vertex)
  14.                 : x(vertex.x), y(vertex.y), z(vertex.z)
  15.         {
  16.                 std::cout << "Copied!" << std::endl;
  17.         }
  18. };
  19. int main()
  20. {
  21.         std::vector<Vertex> vertices;
  22.         vertices.reserve(3);
  23.         vertices.emplace_back(1, 2, 3);
  24.         vertices.emplace_back(14, 4, 6);
  25.         vertices.emplace_back(7, 8, 9);
  26.         std::cin.get();
  27. }
复制代码
运行上述代码,你会看到 "Constructed!" 被打印了3次,而不是 "Copied!",由于 emplace_back 直接在 vector 的内存中构造了 Vertex 对象。 


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用户云卷云舒

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表