本文是在阅读SGI STL v3.3源码中,遇到的一些问题及有意思的点。
本文建立在已经观看过侯捷老师STL源码剖析课程的基础上。是在阅读源码过程中,对其中的内容进行补充、修饰。
顺序型容器
vector
#pragma set woff XXX
#pragma set woff xxx
---- 关闭/抑制 名为xxx
的编译器警告#pragma reset woff xxx
---- 重置命令行中指定的状态的警告(取消set状态)
static_assert
C++11 静态断言static_assert,编译期断言。
static_assert(常量表达式,提示信息)
与断言的区别是,静态断言如果为假,则编译不通过。
noexcept
noexcept
是C++11中的特性,既是一个说明符,也是一个运算符。noexcept
指示函数不会抛出异常,编译器可以优化代码。
noexcept
用法:
return_type function() noexcept
不会抛出异常return_type function() noexcept(常量表达式)
常量表达式为true
,则不会抛出异常。
使用场景:移动构造函数、移动赋值、swap()、析构函数。
- 默认的构造函数、拷贝构造函数、赋值、移动构造、移动赋值均为
noexcept
。 - c++11仍保留throw(),实现和
noexcept
类似功能(但throw不会针对编译器优化),但在c++20已删除。
explicit
explicit
关键字用于构造函数之前,默认关闭了隐式类型转换。
通过构造函数将相应的数据类型转换成为C++类的对象,给编码带来了方便,但并不是每次都正确,为了避免这种情况引入explicit。
const_iterator
const_iterator
可以改变iterator
的值,但不能通过iterator
修改指向元素内容的值。(指向常量的指针)
max_size()
max_size()
函数如下:
size_type max_size() const
{ return size_type(-1) / sizeof(_Tp); }
由源码可以知道,size_type为无符号整形。而-1
我们知道其二进制补码为全1。size_type(-1)
将其强制类型转换为无符号整形的最大值(全1),即表示最大值 2 32 / 64 2^{32/64} 232/64。然后对应的除以一个元素所占大小,即得出最大存放元素数量。
根据操作系统的位数自由推断所能存储的最大元素数量。
copy()
这里所写的copy(iter it1,iter it2,iter it3)
函数是将vector
的拷贝赋值=
,目的地址所存在的元素数多于要插入的元素时的状况:
vector<_Tp,_Alloc>::operator=(const vector<_Tp, _Alloc>& __x)
{
if (&__x != this) {
const size_type __xlen = __x.size();
if (__xlen > capacity()) {
......
}
else if (size() >= __xlen) {
iterator __i = copy(__x.begin(), __x.end(), begin());
destroy(__i, _M_finish);
}
else {
......
}
_M_finish = _M_start + __xlen;
}
return *this;
}
该copy()
函数最终调用的函数如下:
template <class _Tp>
inline _Tp*
__copy_trivial(const _Tp* __first, const _Tp* __last, _Tp* __result) {
memmove(__result, __first, sizeof(_Tp) * (__last - __first));
return __result + (__last - __first);
}
construct()
该函数存在于stl_construct
头文件中,是分配器的一部分。源码如下:
template <class _T1, class _T2>
inline void construct(_T1* __p, const _T2& __value) {
_Construct(__p, __value);
}
template <class _T1>
inline void construct(_T1* __p) {
_Construct(__p);
}
template <class _T1, class _T2>
inline void _Construct(_T1* __p, const _T2& __value) {
new ((void*) __p) _T1(__value); // placement new,调用 _T1::_T1(__value);
}
template <class _T1>
inline void _Construct(_T1* __p) {
new ((void*) __p) _T1();
}
- __p ---- 指针
- __value ---- 初值
- 函数功能 ---- 将初值
__value
设定到指针__p
所指的空间上
函数的作用在于调用相应的构造函数,将地址进行类型转换。
copy_backward()
copy_backward(iter1 first,iter1 end, iter2 res)将元素 [ f i r s t , e n d ) \left[first,end\right) [first,end)复制到以res为尾迭代器的位置 [ r e s − ( e n d − f i r s t ) , r e s ) \left[res-\left(end -first\right),res\right) [res−(end−fi