背景
最近看std的库和相关的API文档,然后就直接调用了。感觉自己好像学会了新工具,实际发现写出来的性能和老手相差很大。首先,建议大家看一下操作系统的书,了解什么是堆栈,内存的复制,回收释放等原理,在此基础上,了解std库就会有更深的见解。下面的例子是在Youtube学习编程优化的总结,分享给需要的同行。
用法优化示例
话不多说,先贴代码:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct Vertex{
float x, y, z;
Vertex(float x, float y, float z):x(x), y(y),z(z){}
Vertex(const Vertex& vertex):x(vertex.x), y(vertex.y), z(vertex.z){
std::cout<<"copied"<<std::endl;
}
};
int main()
{
std::vector<Vertex> vertics;
//vertics.reserve(3);
vertics.push_back({1, 2, 3});
vertics.push_back({4, 5, 6});
vertics.push_back({7, 8, 9});
return 0;
}
这是一个大家都熟悉的写法,参考API文档很容易写成如上的代码。上述代码的执行结果如下:
copied
copied
copied
copied
copied
copied
内存复制了6次,为什么呢?
- 第一次copy,{1,2,3}初始化Vertex,然后copy到vector内,此时vertics的capacity为1。
- 第二次copy,vertics空间不够,进行重新开辟空间,将{1,2,3}copy到新的vectics内。
- 第三次copy,{4,5,6}初始化Vertex,然后copy到vector内,此时vertics的capacity为2。
- 第四,五次copy,vertics空间又不够,再次重新开辟空间,将{1,2,3},{4,5,6}copy到新的vertics内。
- 第六次copy,{7,8,9初始化Vertex,然后copy到vector内,此时vertics的capacity为3。
短短的几行代码就存在如此多的内存复制,按照很多人的习惯,肯定就是循环里写push_back,那么copy的次数将会以O ( n 2 ) O(n^2)O(n2)平方增长。是不是顿时找到自己代码慢的原因了?
如何优化这个代码呢?第一步,预先评估一下vector的空间,使用reserve预留vector的空间。这里强调一下,这里是reserve不是resize,两者区别是:reserve是容器预留空间,不创建元素对象,在创建对象之间,不能引用容器内元素,因此加入新元素的时候,需要用push_back()/insert()等函数;resize()是改变容器大小,并且创建对象。调用函数以后,就可以直接引用容器内对象了,可以使用[]的形式访问对象,或者迭代器访问。如果这里误写成,resize(3) 如下所示:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct Vertex{
float x, y, z;
Vertex(float x =0, float y =0, float z=0):x(x), y(y),z(z){}
Vertex(const Vertex& vertex):x(vertex.x), y(vertex.y), z(vertex.z){
std::cout<<"copied"<<std::endl;
}
};
int main()
{
std::vector<Vertex> vertics;
//vertics.resize(3); // copy 6次
//vertics.resize(3, {0, 0, 0}); // copy 9次
//vertics.reserve(3); // copy 3次
vertics.push_back({1, 2, 3});
vertics.push_back({4, 5, 6});
vertics.push_back({7, 8, 9});
return 0;
}
vertics.push_back这里其实也存在内存copy,可以使用emplace_back()函数,这样最终版的代码如下:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct Vertex{
float x, y, z;
Vertex(float x =0, float y =0, float z=0):x(x), y(y),z(z){}
Vertex(const Vertex& vertex):x(vertex.x), y(vertex.y), z(vertex.z){
std::cout<<"copied"<<std::endl;
}
};
int main()
{
std::vector<Vertex> vertics;
//vertics.resize(3);//, {0,0,0});
vertics.reserve(3);
/*
vertics.push_back({1, 2, 3});
vertics.push_back({4, 5, 6});
vertics.push_back({7, 8, 9});*/
vertics.emplace_back(1,2,3);
vertics.emplace_back(4,5,6);
vertics.emplace_back(7, 8, 9);
return 0;
}
不存在内存copy,有兴趣的同学可以使用一些循环,来测试不同方法的执行速度。
版权声明:本文为zijin0802034原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。