stl中vector特点:
空间连续,当内存不够时候会自动扩容,控容是自动进行的,由分配器来做这件事。
当空间不够的时候,他是在另外一个地方开辟当前空间的俩倍,然后把当前内容都拷贝过去。
参考代码:
通过耗时来看,发现对于vector直接进行寻找某个值和排序之后在寻找某个值,前者耗时不一定比后者慢
#pragma once
#include<iostream>
using std::cout;
using std::cin;
using std::string;
long get_a_target_long()
{
long target = 0;
cout << "target (0~" << RAND_MAX << "):";
cin >> target;
return target;
}
string get_a_target_string()
{
long target = 0;
char buf[10];
cout << "target (0~" << RAND_MAX << "):" << endl;
cin >> target;
sprintf_s(buf, "%d", target);
return string(buf);
}
int compareLongs(const void* a, const void* b)
{
return *(long*)a - *(long*)b;
}
int compareStrings(const void*a, const void*b)
{
if (*(string*)a > *(string*)b)
return 1;
else if (*(string*)a < *(string*)b)
return -1;
else
return 0;
}
#pragma once
#include<vector>
#include<ctime>
#include<algorithm>
#include"function.h"
using std::endl;
using std::vector;
using std::exception;
using std::sort;
namespace stl_vector
{
void test_vector(long& value)
{
cout << "test vector" << endl;
vector<string> c;
char buf[10];
clock_t timeStart = clock();
for (long i = 0; i < value; i++)
{
try {
sprintf_s(buf, 10,"%d", rand());
c.push_back(string(buf));
}
catch (exception& p) {
cout << "i:" << i << " " << p.what() << endl;
abort();
}
}
cout << "milll-second:" << clock() - timeStart << endl;
cout << "vector.size():" << c.size() << endl;
cout << "vector.front():" << c.front().c_str() << endl;
cout << "vector.back():" << c.back().c_str() << endl;
cout << "vector.data():" << c.data() << endl;
cout << "vector.capatity():" << c.capacity() << endl;
string target = get_a_target_string();
{
timeStart = clock();
auto pItem = std::find(c.begin(), c.end(), target);
cout << "find(),mill-seconds:" << (clock() - timeStart) << endl;
if (pItem != c.end())
cout << "found," << (*pItem).c_str() << endl;
else
cout << "not found" << endl;
}
{
timeStart = clock();
sort(c.begin(), c.end());
string* pItem = (string*)bsearch(&target, c.data(), c.size(), sizeof(string),compareStrings);
cout << "sort + bsearch(),mill-seconds:" << (clock() - timeStart) << endl;
if (pItem != NULL)
cout << "found," << (*pItem).c_str() << endl;
else
cout << "not found" << endl;
}
}
}
二、vector中push_back、insert如何增加空间:
通过剖析源码可以看到,vector在每次增加函数的时候会判断当前空间是否够用,如果不够用则以俩倍的空间扩容.
#pragma once
/*
当我们以push_back将新元素插入vector尾端时,该函数首先检查是否还有备用空间,如果有就直接在备用空间上构造元素
并调整迭代器finish,使vector变大。如果没有没有备用空间了,就扩充空间(重新配置,移动数据,释放原空间);
*/
#include<iostream>
using std::iterator;
using std::_Construct;
using std::copy_backward;
using std::_Alloc_allocate;
using std::unexpected;
using std::_Destroy;
using std::_Deallocate;
template <class T,class Alloc = alloc>
class vector {
public:
void push_back(const T& x)
{
if (finish != end_of_storage//还有备用空间
{
_Construct(finish, x);
++finish;//调整水位高度
}
else
{
insert_aux(end(), x);//
}
}
void insert_aux(iterator position, const T& x)
{
if (start != end_of_storage)
{
//在备用空间起始处构造一个元素,并以vector最后一个元素值为初值
_Construct(finish, *(finish - 1));
++finish;
T x_copy = x;
copy_backward(position, finish - 2, finish - 1);
*position = x_copy;
}
else {
const size_type old_size = size();
const size_type len = old_size != 0 ? 2 * old_size : 1;
iterator new_start = _Alloc_allocate(len);
iterator new_finish = new_start;
try {
//将原vector的内容拷贝到新vector
new_finsih = uninitialized_copy(start, position, new_start);
//为新元素设定初值x
_Construct(new_finsih, x);
//调整水位
++new_finish;
//为什么会有这一步么?因为这个Insert_aux函数不只被push_back函数调用,还会被Insert函数调用,所有需要把插入点之后的数据
//在之后的的数据拷贝过来;
//将安插点的原内容也拷贝过来
new_finish = uninitialized_copy(position, finish, new_finish;
}
catch (unexpected &p)
{
cout << "unexception " << p.what();
}
//析构并释放原vector;
_Destroy(begin(), end());
_Deallocate();
start = new_start;
finish = new_finish;
end_of_storage = new_start + len;
}
}
protected :
iterator start;
iterator finish;
iterator end_of_storage;
};