目前在学习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) |