目前在学习STL,看到一个开源的项目MyTinySTL,非常不错。想着照着这个代码自己敲一遍应该也能有些进步。然后就开始了学习过程。
首先分析的是vector
以下是由vector.h关联的所有头文件
终于可以分析vector.h
class vector 先定义了一些类型,
首先定义了下面两个,
typedef mystl::allocator<T> ????????????????allocator_type;
typedef mystl::allocator<T> ????????????????data_allocator;
后续的value_type, pointer等等都是从allocator来的,
typedef typename allocator_type::value_type ?????value_type;
typedef typename allocator_type::pointer ????????pointer;
......
然后定义了三个成员变量
iterator begin_; ???// 表示目前使用空间的头部
iterator end_; ?????// 表示目前使用空间的尾部
iterator cap_; ?????// 表示目前储存空间的尾部
1)定义了构造、复制、移动、析构函数
调用的内部函数 | ||
vector() noexcept | 默认构造 | try_init() |
explicit vector(size_type n) | 显示构造(使用默认值) | fill_init |
vector(size_type n, const value_type& value) | 构造(给定初值) | fill_init |
vector(Iter first, Iter last) | 构造函数 | range_init |
vector(const vector& rhs) | 拷贝构造 | range_init |
vector(vector&& rhs) noexcept | 移动构造 | range_init |
vector(std::initializer_list<value_type> ilist) | 初始化列表构造 | range_init |
vector& operator=(const vector& rhs); | 拷贝赋值操作符 | |
vector& operator=(vector&& rhs) noexcept; | 移动赋值 | rhs的成员要设置为nullptr |
vector& operator=(std::initializer_list<value_type> ilist) | 初始化赋值 | 先构造tmp,然后使用swap交换 |
~vector() | 析构函数 | destroy_and_recover 然后成员变量设置为nullptr |
2)定义了迭代器相关操作
begin() | return begin_; |
end() | return end_; |
rbegin() | return reverse_iterator(end()); |
rend() | return reverse_iterator(begin()); |
cbegin | return begin(); |
cend() const noexcept; | return end(); |
crbegin() | return rbegin(); |
crend() | return rend(); |
3)容器相关操作
empty() | return begin_ == end_; |
size() | end_ - begin_ |
max_size() | |
capacity() | |
reserve() | 预留空间大小 |
shrink_to_fit() | 放弃多余的容量 |
4)访问元素相关操作
operatro[] | return *(begin_ + n); |
at() | return (*this)[n]; |
front | return *begin_; |
back() | return *(end_ - 1); |
data() | return begin_; |
5)修改容器相关操作
调用内部函数 | ||
assign() | fill_assign/ copy_assign | |
emplace() | 在pos位置就地构造元素,避免额外的复制或移动开销;分为三种情况
| |
emplace_back() | 在尾部就地构造元素,避免额外的复制或移动开销 | 直接使用构造参数列表添加元素 |
push_back | 在尾部插入元素 | 需要先构造出一个元素,然后再放到缓冲区;性能上不如emplace_back() |
pop_back() | 弹出尾部元素 | |
insert() | 类似于emplace,reallocate_insert替换了reallocate_emplace | |
erase() | 删除pos位置的元素 | |
clear() | ||
resize() | 重置大小,分两种情况 | |
reverse() | ||
swap() | 与另一个vector交换 |
6)helper_functions
调用的函数 | ||
try_init() | 分配16个空间 | |
init_space(size_type size, size_type cap); | 分配制定空间 | |
fill_init(size_type n, const value_type& value); | uninitialized_fill_n | |
range_init(Iter first, Iter last); | ||
destroy_and_recover(iterator first, iterator last, size_type n); | destroy deallocate | |
get_new_cap(size_type add_size); | ||
fill_assign(size_type n , const value_type& value); | ||
copy_assign(IIter first, IIter last, input_iterator_tag); | ||
copy_assign(FIter first, FIter last, forward_iterator_tag); | ||
reallocate_emplace(iterator pos, Args&& ...args); | 重新分配一块新的空间,并在pos处就地构造元素 | |
reallocate_insert(iterator pos, const value_type& value); | 和上一个区别就像emplace 和 insert区别一样,emplace不要求传入一个对象,而只需要创造对象所需的参数,而insert需要先把对象构造出来,再把对象拷贝过去 | |
fill_insert(iterator pos, size_type n, const value_type& value); | 填充n个相同的value | |
copy_insert(iterator pos, IIter first, IIter last); | 把另外一个容器的[first,last)拷贝到现有的容器中 | |
reinsert(size_type size); | 重新分配一个vector,把原来的元素拷贝到新分配的地方,顺便shrink了一下,因为end_等于cap_ |
copy_assign根据第三个参数有两个版本,
copy(xx,xx,input_iterator_tag)
copy(xx,xx,forward_iterator_tag)
其中的实现方式也不同,
需要分析一下这两个tag的区别
input_iterator_tag 只能读,不能写
forward_iterator_tag 既能读又能写
7)重载了对于两个vector的比较操作符
函数名 | 说明 | |
operator== | ||
operator< | 字典排序 | |
operator!= | ||
operator> | ||
operator<= | ||
operator>= |
8)重载了对于两个vector的比较操作符
swqp(vector<T>& lhs, vector<T>& rhs) |