首先说一句:vector不优化的话实在是太~~慢了;
vector的工作机制很简单,当我们向vector中push一个元素,且vector中的容量不够时,vector就会寻找另一块能够容纳新加入元素后的内存块【有的编译器是新内存块相对旧内存块的大小指数增长,有的是线性增长,本菜的编译器是线性增长】,然后旧内存块和新元素按照顺序copy新内存块中:
如下:
#include<iostream>
#include<vector>
using namespace std;
class test {
int x;
public:
test() {}
test(int scr):x(scr) {
//cout << "Create" << endl;
}
test(const test& scr) {
memcpy(this, &scr, sizeof(scr));
cout << "copy" << endl;
}
~test() {
//cout << "Destroyed" << endl;
}
};
int main() {
vector<test> st;
test A, B, C;
st.push_back(A);
st.push_back(B);
st.push_back(C);
cout << st.size() << endl;
cin.get();
}
运行结果:
因为是线性增长的,所以新内存相对旧内存只多了一个位置,所以copy了1+2+3次;
这无疑会消耗很多时间,所以我们就可以使用vector的reserve函数了优化这个过程了,与这个函数对标的是resize函数,下面来介绍着两种函数是怎么工作的,然后在知道了工作原理的基础上来讲怎么优化;
reserve:
这个函数和其名字一样,是在vector容器中预留一些位置,但是这些位置不是元素实例,而是单单地开放对等的空间而已;
比如我们有以下代码:
#include<iostream>
#include<vector>
using namespace std;
int main() {
vector<int> test;
test.reserve(10);
test[1] = 1;
}
程序会报错:
因为并不存在实例化的int型,它只是预留了与10个int型对等的空间大小;
然后是resize函数了;
这个函数就会在开辟空间的同时进行实例化:
还是上面的代码:
#include<iostream>
#include<vector>
using namespace std;
int main() {
vector<int> test;
test.resize(10);
test[1] = 1;
}
程序可以正常运行:
因为resize实例化了int型;
然后如何优化呢?这里主要围绕reserve来展开:
对比刚开始的那串代码,如何我们我先预留出一些空间,如何再push_back的话,那么就有如下场景:
#include<iostream>
#include<vector>
using namespace std;
class test {
int x;
public:
test() {}
test(int scr) :x(scr) {
cout << "Create" << endl;
}
test(const test& scr) {
memcpy(this, &scr, sizeof(scr));
cout << "copy" << endl;
}
~test() {
cout << "Destroyed" << endl;
}
};
int main() {
vector<test> st;
st.reserve(10);
st.push_back(1);
st.push_back(2);
st.push_back(3);
cout << st.size() << endl;
cin.get();
}
运行结果:
嗯~相对第一次的6次copy,效率高了一倍呢;
那为什么会这样呢?
很简单,程序先用push_back里的值实例化了一个无名变量【Create】,如何讲这个无名变量的copy到预留空间中了【Copy】,如果因为无名变量没有用,所以就将无名变量释放掉了【Destroyed】,然后这个工作持续了3次;
那我们能不能进一步优化呢?
当然可以,我们可以利用emplace_back这个函数;
这个函数如果在vector容器的预留空间不够的情况下,是和push_back函数相同的,即先实例化一个无名变量,然后开新内存copy旧内存,但是在有预留空间的情况下,emplace的效率就要高很多,看下面代码:
#include<iostream>
#include<vector>
using namespace std;
class test {
int x;
public:
test() {}
test(int scr) :x(scr) {
cout << "Create" << endl;
}
test(const test& scr) {
memcpy(this, &scr, sizeof(scr));
cout << "copy" << endl;
}
~test() {
cout << "Destroyed" << endl;
}
};
int main() {
vector<test> st;
st.reserve(10);
st.emplace_back(1);
st.emplace_back(2);
st.emplace_back(3);
st.emplace_back(4);
cout << st.size() << endl;
cin.get();
}
运行结果:
由此可知,emplace是直接对预留空间操作,即直接在预留空间在实例化对象,所以我们可以少去很多Destroy和Copy的时间开销,由此达到优化的目的;
好了,基本的就这些了,以后会继续更新容器的优化;