1.vector的介绍和使用
1.vector的介绍
- vector是表示可变大小数组的序列容器。
- 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素 进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自 动处理。
- 本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小 为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是
一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大 小。- vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存 储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是
对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。- 因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增 长。
- 与其它动态序列容器相比(deque, list and forward_list), vector在访问元素的时候更加高效,在末 尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起list和forward_list 统一的迭代器和引用更好。
2.vector的使用
vector的学习其实和string的学习相差不大,所以我们同样通过函数来实现。
capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。
这个问题经常会考察,不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义
的。vs是PJ版本STL,g++是SGI版本STL。
reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问
题。
resize在开空间的同时还会进行初始化,影响size。
2.vector的深度剖析
void test_vector1()
{
/*vector<int>v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
for (auto e : v)
{
cout << e << " ";
}
cout << endl;*/
vector<int >v(10,1);
for (size_t i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
cout << endl;
vector<int>::iterator it = v.begin();//迭代器
while (it != v.end())
{
cout << *it << " ";
++it;
}
cout << endl;
for (auto e : v)//范围for
{
cout << e << " ";
}
cout << endl;
}
void test_vector2()
{
size_t sz;
vector<int> v;
v.reserve(100);//开辟空间
sz = v.capacity();
cout << "making v grow:\n";
for (size_t i = 0; i < 100; ++i)
{
v.push_back(i);
if (sz != v.capacity())
{
sz = v.capacity();
cout << "capacity changed:" << sz << endl;
}
}
cout << v.size() <<endl;
cout << v.capacity() << endl;
v.reserve(10);//开辟的空间大于原来空间容量就增大
cout << v.capacity() << endl;
cout << v.size() << endl;
cout << "---------------------------------" << endl;
cout << v.size() << endl;
cout << v.capacity() << endl;
v.resize(10);//缩容
cout << v.size() << endl;
cout << v.capacity() << endl;
v.shrink_to_fit();//缩容
cout << v.size() << endl;
cout << v.capacity() << endl;
vector<int>a;
a.resize(10, 1);
for (auto e : a)
{
cout << e << " ";
}
cout << endl;
}
void test_vector3()
{
vector<int> v;
//尾插数据
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
//vector<int>::iterator pos = find(v.begin(), v.end(), 3);
//查找数据为3的位置
auto pos = find(v.begin(), v.end(), 3);
if (pos != v.end())
{
v.insert(pos,30);//在该位置进行插入
}
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
v.insert(v.begin(), 0);
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
v.insert(v.begin() + 2, 0);//在下标为2的位置插入0
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
string s("abcd");
v.insert(v.begin(), s.begin(), s.end());//在v的开始插入字符串S
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
v.insert(v.end(), s.begin(), s.end());
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
}
void test_vector4()
{
vector<string>v;
string s1("草莓");
v.push_back(s1);
v.push_back(string("香蕉"));
v.push_back("草莓");
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
}
vector代表的是顺序表,vector里的每一个元素都是一个string类。
3.vector的模拟实现
先定义一个命名空间Myvector,里面定义类和函数来完成模拟实现。
namespace Myvector
{
template<class T>//函数模版
class vector
{
public:
typedef T* iterator;//迭代器
typedef const T* const_iterator;
private:
iterator _start = nullptr;
iterator _finish = nullptr;
iterator _endofstorage = nullptr;
};
}
iterator begin()//迭代器的开始位置
{
return _start;
}
iterator end()//迭代器的结束位置
{
return _finish;
}
const iterator begin()const
{
return _start;
}
const iterator end()const
{
return _finish;
}
vector()//无参构造函数
{
}
vector(const vector<T>& v)//构造函数
{
reserve(v.capacity());
for (auto& e : v)
{
push_back(e);
}
}
// vector<int> v1 = { 1,2,3,4,5,6,7,8,9,10 };
vector(initializer_list<T> il)//构造函数
{
il.reserve(il.capacity());
for (auto& e : il)
{
push_back(e);
}
}
template<class InputIterator>
vector(InputIterator first, InputIterator last)//first为头指针,last为尾指针
{
while (first != last)
{
push_back(*first);
++first;
}
}
vector(size_t n, const T& val = T())//构造函数
{
reserve(n);
for (size_t i = 0; i < n; i++)
{
push_back(val);
}
}
vector(int n, const T& val = T())
{
reserve(n);
for (int i - 0; i < n; i++)
{
push_back(val);
}
}
void swap(vector<T>& v)//交换
{
std::swap(_start, v._start);//调用库里的交换函数
std::swap(_finish, v._finish);
std::swap(_endofstorage, v._endofstorage);
}
vector operator=(vector<T> v)//赋值重载
{
swap(v);
return *this;
}
~vector()//析构函数
{
delete[]_start;
_start = _finish = _endofstorage = nullptr;
}
size_t size()//返回数据数量
{
return _finish - _start;
}
T& operator[](size_t pos)
{
assert(pos < size());
return _start[pos];
}
const T& operator[](size_t pos)const
{
assert(pos < size());
return _start[pos];
}
size_t capacity()//返回容量大小
{
return _endofstorage - _start;
}
void reserve(size_t n)//扩容,空间为n
{
if (n > capacity())//要扩容的目标空间大于原有空间
{
T* tmp = new T[n];
size_t old_size = size();
for (size_t i = 0; i < old_size; ++i)
{
tmp[i] = _start[i];
}
delete[]_start;
_start = tmp;
_finish = tmp + old_size;
_endofstorage = tmp + n;
}
}
void resize(size_t n, const T& val = T())//缩容
{
if (n > size())
{
reserve(n);
while (_finish < _start + n)
{
*_finish = val;
++_finish;
}
}
else
_finshi = _start + n;
}
void push_back(const T& val)//尾插
{
insert(end(), val);
}
void pop_back()
{
/*assert(!empty);
--_finish;*/
erase(end() - 1);
}
bool empty()
{
return _finish == _start;
}
void insert(iterator pos, const T& val)//插入
{
assert(pos >= _start);
assert(pos << _finish);
if (_finish = _endofstorage)
{
size_t len = pos - _start;
reserve(capacity() == 0 ? 4 : 2 * capacity());
pos = _start + len;
}
iterator it = _finish - 1;
while (it >= pos)
{
*(it + 1) = *it;
--it;
}
*pos = val;
++_finish;
}
iterator erase(iterator pos)
{
assert(pos <= _finish);
assert(pos >= _start);
iterator it = pos + 1;
while (it <= _finish)
{
*(it - 1) = *it;
++it;
}
--_finish;
return pos;
}
测试代码:
template<class T>
void print_vector(const vector<T>& v)
{
for (size_t i = 0; i < v.end(); i++)
{
cout << v[i] << " ";
}
cout << endl;
//typename vector<T>::const_iterator it = v.begin();
/*auto it = v.begin();
while (it != v.end())
{
cout << *it << " ";
++it;
}
cout << endl;
for (auto e : v)
{
cout << e << " ";
}
cout << endl;*/
}
void test_vector1()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
print_vector(v);
vector<double> v2;
v2.push_back(1.1);
v2.push_back(2.2);
v2.push_back(3.1);
print_vector(v2);
v2.insert(v2.begin(), 11.11);
print_vector(v2);
v2.insert(v2.begin(), 11.11);
print_vector(v2);
v2.insert(v2.begin(), 11.11);
print_vector(v2);
v2.insert(v2.begin(), 11.11);
print_vector(v2);
v2.insert(v2.begin(), 11.11);
print_vector(v2);
v2.erase(v2.begin());
print_vector(v2);
v2.erase(v2.begin() + 4);
print_vector(v2);
/*for (size_t i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
cout << endl;
vector<int>::iterator it = v.begin();
while (it != v.end())
{
cout << *it << " ";
++it;
}
cout << endl;
for (auto e : v)
{
cout << e << " ";
}
cout << endl;*/
}
void test_vector2()
{
int i = 1;
int j = int();
int k = int(2);
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
v1.push_back(4);
v1.push_back(4);
print_vector(v1);
v1.resize(10);
print_vector(v1);
v1.resize(3);
print_vector(v1);
}
void test_vector3()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
v1.push_back(4);
v1.push_back(4);
print_vector(v1);
v1.pop_back();
vector<int> v2(v1);
print_vector(v2);
vector<int> v3;
v3.push_back(10);
v3.push_back(20);
v3.push_back(30);
v1 = v3;
print_vector(v1);
print_vector(v3);
}
void test_vector4()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
print_vector(v1);
vector<int> v2(v1.begin() + 1, v1.end() - 1);
print_vector(v2);
string str("abcd");
vector<int> v3(str.begin(), str.end());
print_vector(v3);
}
void test_vector5()
{
vector<int> v1(10, 1);
print_vector(v1);
vector<int> v2(10u, 1);
print_vector(v2);
vector<char> v3(10, 'a');
print_vector(v3);
}
void test_vector6()
{
auto x = { 1,2,3,4,5,6,7,8,9,10 };
cout << typeid(x).name() << endl;
cout << sizeof(x) << endl;
initializer_list<int> y = { 1,2,3,4,5,6,7 };
// 单参数的构造函数,隐式类型转换
string str = "11111"; // 构造 + 拷贝构造 -> 优化 直接构造
const string& str1 = "11111"; // 构造临时对象,引用的是临时对象
vector<string> v;
v.push_back(str);
v.push_back(string("22222"));
v.push_back("33333");
int i = 1;
// 不推荐 -- C++11
//int j = { 1 };
int k{ 1 };
// 跟上面类似
// 隐式类型转换+优化
//vector<int> v1 = { 1,2,3,4,5,6,7,8,9,10 };
vector<int> v1 { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
// 直接构造
vector<int> v2({ 10,20,30,40 });
for (auto e : v2)
{
cout << e << " ";
}
cout << endl;
}
void test_vector7()
{
// 20:10继续
vector<string> v;
v.push_back("11111");
v.push_back("22222");
v.push_back("33333");
v.push_back("44444");
v.push_back("55555");
for (auto& e : v)
{
cout << e << " ";
}
cout << endl;
}
void test_vector8()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
v1.push_back(5);
v1.push_back(6);
v1.push_back(7);
v1.push_back(8);
print_vector(v1);
// insert以后,it就失效了,不要使用了
vector<int>::iterator it = v1.begin() + 3;
v1.insert(it, 40);
print_vector(v1);
it = v1.begin() + 3;
cout << *it << endl;
}
void test_vector9()
{
//std::vector<int> v1;
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
v1.push_back(4);
v1.push_back(5);
//v1.push_back(4);
// 删除偶数 -- 迭代器失效以后,不要直接使用,如果要使用按规则重新更新后使用
//std::vector<int>::iterator it = v1.begin();
vector<int>::iterator it = v1.begin();
// erase删除的迭代器如果是最后一个元素,删除之后it已经超过end
// 此时迭代器是无效的,++it导致程序崩溃
//cout << typeid(it).name() << endl;
while (it != v1.end())
{
if (*it % 2 == 0)
{
it = v1.erase(it);
}
else
{
++it;
}
}
//print_vector(v1);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
}
}