1 vector简介
顺序存储, 初始化过程会分配一定量空间, 在尾部插入会很快, 但是在中间插入元素, 会把之后所有元素向后平移, 所以较慢(中间删除元素同理). 如果元素个数超过当前限制, 会重新分配更大空间, 再把原容器中所有元素都拷贝到新的容器中.
- 优点: 支持随机访问(用下标访问), 性能较好
- 缺点: 除了操作尾部元素, 增删中间元素性能较差
2 vector接口
- push_back() 尾插数据
- pop_back() 尾删数据
- front() 第一个元素
- back() 最后一个元素
构造:
void vector_constructor_test() {int array[] = {0,1,2,3,4,5,6,7,8,9};vector<int> testVec = TestUtils::getInstance()->getVectorByArr(PARAM_ARRAY(array));TestUtils::getInstance()->showVector(testVec);vector<int> testVec1(testVec.begin(), testVec.end()); // copy [testVec.begin(), testVec.end())TestUtils::getInstance()->showVector(testVec1);vector<int> testVec2(&array[0], &array[8]); // copy array[0, 8)TestUtils::getInstance()->showVector(testVec2);vector<int> testVec3(10, 100);TestUtils::getInstance()->showVector(testVec3); // testVec3 have 10 elements, every element is 100vector<int> testVec4;testVec4.assign(testVec.begin(), testVec.end()); // copy testVec[begin(), end())TestUtils::getInstance()->showVector(testVec4);
}
结果:
2.1 vector容量和大小
void vector_size_capacity_test() {int array[] = {0,1,2,3,4,5,6,7,8,9};vector<int> testVec = TestUtils::getInstance()->getVectorByArr(PARAM_ARRAY(array));cout << "testVec.size(): " << testVec.size() << endl;cout << "testVec.capacity(): " << testVec.capacity() << endl;testVec.resize(15); // if resize number > vec.size(), willTestUtils::getInstance()->showVector(testVec); // fill with 0cout << "testVec.size(): " << testVec.size() << endl;cout << "testVec.capacity(): " << testVec.capacity() << endl;testVec.resize(5);TestUtils::getInstance()->showVector(testVec);cout << "testVec.size(): " << testVec.size() << endl;cout << "testVec.capacity(): " << testVec.capacity() << endl;testVec.resize(15, 8);TestUtils::getInstance()->showVector(testVec);cout << "testVec.size(): " << testVec.size() << endl;cout << "testVec.capacity(): " << testVec.capacity() << endl;
}
结果为:
2.2 增删
void vector_add_delete_test() {int array[] = {0,1,2,3,4,5,6,7,8,9};vector<int> testVec = TestUtils::getInstance()->getVectorByArr(PARAM_ARRAY(array));testVec.push_back(10); // add to backTestUtils::getInstance()->showVector(testVec);testVec.pop_back(); // delete backTestUtils::getInstance()->showVector(testVec);testVec.insert(testVec.begin(), 10); // insert to headTestUtils::getInstance()->showVector(testVec);testVec.insert(testVec.begin(), 2, 100); // insert two 100 to headTestUtils::getInstance()->showVector(testVec);testVec.erase(testVec.begin()); // delete headTestUtils::getInstance()->showVector(testVec);testVec.erase(testVec.begin(), testVec.begin() + 2);// delete head to head + 2(not include head + 2)TestUtils::getInstance()->showVector(testVec);cout << "testVec.front(): " << testVec.front() << endl;cout << "testVec.back(): " << testVec.back() << endl;
}
结果:
2.2 互换
void vector_swap_test() {int array1[] = {0,1,2,3,4,5,6,7,8,9};vector<int> testVec1 = TestUtils::getInstance()->getVectorByArr(PARAM_ARRAY(array1));int array2[] = {10,11,12,13,14,15,16,17,18,19};vector<int> testVec2 = TestUtils::getInstance()->getVectorByArr(PARAM_ARRAY(array2));TestUtils::getInstance()->showVector(testVec1);TestUtils::getInstance()->showVector(testVec2);testVec1.swap(testVec2);TestUtils::getInstance()->showVector(testVec1);TestUtils::getInstance()->showVector(testVec2);
}
运行结果为:
用途如以下测试代码:
void vector_swap_test1() {vector<int> testVec;for (int i = 0; i < 100000; i ++) {testVec.push_back(i);}cout << "testVec.size(): " << testVec.size() << endl;cout << "testVec.capacity(): " << testVec.capacity() << endl;testVec.resize(10);cout << "testVec.size(): " << testVec.size() << endl;cout << "testVec.capacity(): " << testVec.capacity() << endl;
}
结果是:
所以可以用swap收缩:
void vector_swap_test1() {vector<int> testVec;for (int i = 0; i < 100000; i ++) {testVec.push_back(i);}cout << "testVec.size(): " << testVec.size() << endl;cout << "testVec.capacity(): " << testVec.capacity() << endl;testVec.resize(10);cout << "testVec.size(): " << testVec.size() << endl;cout << "testVec.capacity(): " << testVec.capacity() << endl;vector<int>(testVec).swap(testVec);cout << "testVec.size(): " << testVec.size() << endl;cout << "testVec.capacity(): " << testVec.capacity() << endl;
}
结果是:
原因是vector<int>(testVec).swap(testVec);调用时, 相当于用testVec创建了一个匿名对象vector<int> (testVec), 这个匿名对象的size和capacity都是10, 元素就是testVec的十个元素, 然后这个匿名对象和testVec作了交换之后, 匿名对象变成了十万个元素, 而testVec变成了size和capacity都是10, 匿名对象在行结束后立刻销毁, 所以原来哪个100000个元素的匿名对象就销毁了, 这样就达到了缩容的目的.
2.3 预留空间
reserve. 调用reserve可以减少重新分配空间的时间, 但是和resize不同的是, 元素不会被初始化为0.
比如有如下函数, 我们可以验证vector在加入了100000个元素之后一共重新分配了多少次内存.有两种方法:
- 看序列首元素地址改变了多少次
- 看vector的size和capacity相等了多少次
void vector_allocate_test1(){vector<int> testVec;int *p = NULL;int number1 = 0;int number2 = 0;for (int i = 0; i < 100000; i ++) {if (testVec.size() == testVec.capacity())number1 ++;testVec.push_back(i);if (p != &testVec[0]) {p = &testVec[0];number2 ++;}}cout << "number1 = " << number1 << endl;cout << "number2 = " << number2 << endl;
}
结果是:
发现重新分配了18次.我们可以用以下代码来测试一下性能:
void vector_allocate_test2(){double startTime = TestUtils::getInstance()->getNowMillisecond();vector<int> testVec1;for (int i = 0; i < 100000; i ++) {testVec1.push_back(i);}double endTime = TestUtils::getInstance()->getNowMillisecond();cout << "use " << endTime - startTime << "ms" << endl;startTime = TestUtils::getInstance()->getNowMillisecond();vector<int> testVec2;testVec2.reserve(100000);for (int i = 0; i < 100000; i ++) {testVec2.push_back(i);}endTime = TestUtils::getInstance()->getNowMillisecond();cout << "use " << endTime - startTime << "ms after reserve" << endl;
}
结果为:
3 迭代器
假如有如下一个vector:
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))vector<int> intVec;
int array[] = {0, 1, 2, 3, 4, 5};
for (int i = 0; i < ARRAY_SIZE(array); i ++) {inVec.push_back(arr[i]);
}
那么如下迭代器:
vector<int>::iterator beginIter = intVec.begin(); //beginIter指向vector首元素vector<int>::iterator endIter = intVec.end(); //endIter指向vector最后元素的下一个位置