STL源代码学习(vector篇)
#include <concept_checks.h>
#include<stl_allocate.h> /// The vector base class's constructor and destructor allocate
///(but don't initialize) storage. This makes exception safety easier.
template <class _Tp, class _Alloc>
class _Vector_base {
public:
typedef _Alloc allocator_type;
allocator_type get_allocator() const { return allocator_type(); } _Vector_base(const _Alloc&)
: _M_start(0), _M_finish(0), _M_end_of_storage(0) {}
_Vector_base(size_t __n, const _Alloc&)
: _M_start(0), _M_finish(0), _M_end_of_storage(0)
{
_M_start = _M_allocate(__n); ///分配内存
_M_finish = _M_start;
_M_end_of_storage = _M_start + __n;
} ~_Vector_base()
{
_M_deallocate(_M_start, _M_end_of_storage - _M_start); ///回收内存
} protected:
_Tp* _M_start;
_Tp* _M_finish;
_Tp* _M_end_of_storage; typedef simple_alloc<_Tp, _Alloc> _M_data_allocator; ///将_Alloc用simple_alloc包裹,更方便使用
_Tp* _M_allocate(size_t __n)
{ return _M_data_allocator::allocate(__n); }
void _M_deallocate(_Tp* __p, size_t __n)
{ _M_data_allocator::deallocate(__p, __n); }
}; template <class _Tp, class _Alloc = Stl_Default_Alloc >
class vector : protected _Vector_base<_Tp, _Alloc>
{
__STL_CLASS_REQUIRES(_Tp, _Assignable); ///vector中的元素必须可赋值,在此处检查 private:
typedef _Vector_base<_Tp, _Alloc> _Base;
public:
typedef _Tp value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type* iterator;
typedef const value_type* const_iterator; ///const_iterator实际是指向const value_type类型的指针
typedef value_type& reference;
typedef const value_type& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type; typedef typename _Base::allocator_type allocator_type;
allocator_type get_allocator() const { return _Base::get_allocator(); } ///先定义const_reverse_iterator,再定义reverse_iterator,否则先定义的reverse_iterator
///会将全局空间内的reverse_iterator覆盖掉,从而在定义const_reverse_iterator时,出现错误
typedef reverse_iterator<const_iterator, value_type, const_reference,
difference_type> const_reverse_iterator;
typedef reverse_iterator<iterator, value_type, reference, difference_type>
reverse_iterator; protected:
using _Base::_M_allocate;
using _Base::_M_deallocate;
using _Base::_M_start;
using _Base::_M_finish;
using _Base::_M_end_of_storage;
protected:
void _M_insert_aux(iterator __position, const _Tp& __x);
void _M_insert_aux(iterator __position); public:
iterator begin() { return _M_start; }
const_iterator begin() const { return _M_start; } iterator end() { return _M_finish; }
const_iterator end() const { return _M_finish; } reverse_iterator rbegin()
{ return reverse_iterator(end()); }
const_reverse_iterator rbegin() const
{ return const_reverse_iterator(end()); } reverse_iterator rend()
{ return reverse_iterator(begin()); }
const_reverse_iterator rend() const
{ return const_reverse_iterator(begin()); } size_type size() const
{ return size_type(end() - begin()); }
size_type max_size() const
{ return size_type(-1) / sizeof(_Tp); }
size_type capacity() const
{ return size_type(_M_end_of_storage - begin()); }
bool empty() const
{ return begin() == end(); } ///对operator[]的重载,使得该函数的使用性更广
reference operator[](size_type __n) { return *(begin() + __n); }
const_reference operator[](size_type __n) const { return *(begin() + __n); } explicit vector(const allocator_type& __a = allocator_type())
: _Base(__a) {} vector(size_type __n, const _Tp& __value,
const allocator_type& __a = allocator_type())
: _Base(__n, __a)
{
///分配内存在基类的构造函数中完毕,此处仅进行初始化
_M_finish = uninitialized_fill_n(_M_start, __n, __value);
} explicit vector(size_type __n)
: _Base(__n, allocator_type())
{ _M_finish = uninitialized_fill_n(_M_start, __n, _Tp()); } vector(const vector<_Tp, _Alloc>& __x)
: _Base(__x.size(), __x.get_allocator())
{ _M_finish = uninitialized_copy(__x.begin(), __x.end(), _M_start); } /// Check whether it's an integral type. If so, it's not an iterator.
template <class _InputIterator>
vector(_InputIterator __first, _InputIterator __last,
const allocator_type& __a = allocator_type()) : _Base(__a) {
typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
_M_initialize_aux(__first, __last, _Integral());
} template <class _Integer>
void _M_initialize_aux(_Integer __n, _Integer __value, __true_type) {
_M_start = _M_allocate(__n);
_M_end_of_storage = _M_start + __n;
_M_finish = uninitialized_fill_n(_M_start, __n, __value);
} template <class _InputIterator>
void _M_initialize_aux(_InputIterator __first, _InputIterator __last,
__false_type) {
_M_range_initialize(__first, __last, __ITERATOR_CATEGORY(__first));
} ~vector() {
destroy(_M_start, _M_finish); ///析构全部对象,回收内存在基类析构函数中完毕
} vector<_Tp, _Alloc>& operator=(const vector<_Tp, _Alloc>& __x);
void reserve(size_type __n) {
if (capacity() < __n) {
const size_type __old_size = size(); ///又一次分配内存,并将原内存数据copy到新分配的内存
iterator __tmp = _M_allocate_and_copy(__n, _M_start, _M_finish); destroy(_M_start, _M_finish); ///一一析构原内存中的对象
_M_deallocate(_M_start, _M_end_of_storage - _M_start); ///归还原内存
_M_start = __tmp;
_M_finish = __tmp + __old_size;
_M_end_of_storage = _M_start + __n;
}
} /// assign(), a generalized assignment member function. Two
/// versions: one that takes a count, and one that takes a range.
/// The range version is a member template, so we dispatch on whether
/// or not the type is an integer. void assign(size_type __n, const _Tp& __val) { _M_fill_assign(__n, __val); }
void _M_fill_assign(size_type __n, const _Tp& __val); template <class _InputIterator>
void assign(_InputIterator __first, _InputIterator __last) {
typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
_M_assign_dispatch(__first, __last, _Integral());
} template <class _Integer>
void _M_assign_dispatch(_Integer __n, _Integer __val, __true_type)
{ _M_fill_assign((size_type) __n, (_Tp) __val); } template <class _InputIter>
void _M_assign_dispatch(_InputIter __first, _InputIter __last, __false_type)
{ _M_assign_aux(__first, __last, __ITERATOR_CATEGORY(__first)); } template <class _InputIterator>
void _M_assign_aux(_InputIterator __first, _InputIterator __last,
input_iterator_tag); template <class _ForwardIterator>
void _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last,
forward_iterator_tag); reference front() { return *begin(); }
const_reference front() const { return *begin(); }
reference back() { return *(end() - 1); }
const_reference back() const { return *(end() - 1); } void push_back(const _Tp& __x) {
if (_M_finish != _M_end_of_storage) { ///vector尚有空间
construct(_M_finish, __x);
++_M_finish;
}
else
_M_insert_aux(end(), __x);
} void push_back() { if (_M_finish != _M_end_of_storage) {
construct(_M_finish);
++_M_finish;
}
else
_M_insert_aux(end());
} void swap(vector<_Tp, _Alloc>& __x) {
///vector的swap方法,仅仅是将其三个标志指针交换,因此会有非常高的效率
__STD::swap(_M_start, __x._M_start);
__STD::swap(_M_finish, __x._M_finish);
__STD::swap(_M_end_of_storage, __x._M_end_of_storage);
} iterator insert(iterator __position, const _Tp& __x) {
size_type __n = __position - begin();
if (_M_finish != _M_end_of_storage && __position == end()) { ///vector尚有空间,并且插入位置为末尾
construct(_M_finish, __x);
++_M_finish;
}
else
_M_insert_aux(__position, __x);
return begin() + __n;
} iterator insert(iterator __position) {
size_type __n = __position - begin();
if (_M_finish != _M_end_of_storage && __position == end()) {
construct(_M_finish);
++_M_finish;
}
else
_M_insert_aux(__position);
return begin() + __n;
} /// Check whether it's an integral type. If so, it's not an iterator.
template <class _InputIterator>
void insert(iterator __pos, _InputIterator __first, _InputIterator __last) {
typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
_M_insert_dispatch(__pos, __first, __last, _Integral());
} template <class _Integer>
void _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __val,
__true_type)
{ _M_fill_insert(__pos, (size_type) __n, (_Tp) __val); } template <class _InputIterator>
void _M_insert_dispatch(iterator __pos,
_InputIterator __first, _InputIterator __last,
__false_type) {
_M_range_insert(__pos, __first, __last, __ITERATOR_CATEGORY(__first));
} void insert (iterator __pos, size_type __n, const _Tp& __x)
{ _M_fill_insert(__pos, __n, __x); } void _M_fill_insert (iterator __pos, size_type __n, const _Tp& __x); void pop_back() {
--_M_finish;
destroy(_M_finish);
}
iterator erase(iterator __position) { ///将__position以后的每一个对象依次向前移动一位,再将最后一个元素析构,效率不高(删除尾部元素除外)
if (__position + 1 != end())
copy(__position + 1, _M_finish, __position);
--_M_finish;
destroy(_M_finish);
return __position;
}
iterator erase(iterator __first, iterator __last) {
///还是通过大量移动来完毕的
iterator __i = copy(__last, _M_finish, __first);
destroy(__i, _M_finish);
_M_finish = _M_finish - (__last - __first);
return __first;
} void resize(size_type __new_size, const _Tp& __x) {
if (__new_size < size())
erase(begin() + __new_size, end());
else
insert(end(), __new_size - size(), __x);
}
void resize(size_type __new_size) { resize(__new_size, _Tp()); }
void clear() { erase(begin(), end()); } protected: template <class _ForwardIterator>
iterator _M_allocate_and_copy(size_type __n, _ForwardIterator __first,
_ForwardIterator __last)
{
iterator __result = _M_allocate(__n);
try {
uninitialized_copy(__first, __last, __result);
return __result;
}catch(...){
_M_deallocate(__result, __n); ///若失败,归还分配内存,防止内存泄露
} } template <class _InputIterator>
void _M_range_initialize(_InputIterator __first,
_InputIterator __last, input_iterator_tag)
{
///_InputIterator属性决定无法计算其区间内的元素个数,因此仅仅能对每一个对象都调用push_back插入
///此行为有可能导致过多次数的内存分配
for ( ; __first != __last; ++__first)
push_back(*__first);
} /// This function is only called by the constructor.
template <class _ForwardIterator>
void _M_range_initialize(_ForwardIterator __first,
_ForwardIterator __last, forward_iterator_tag)
{
size_type __n = 0;
distance(__first, __last, __n); ///先计算元素个数 ///再依据元素个数分配合适的内存,防止了多次内存分配以及由其导致的大量对象的构造和析构
_M_start = _M_allocate(__n);
_M_end_of_storage = _M_start + __n;
_M_finish = uninitialized_copy(__first, __last, _M_start);
} template <class _InputIterator>
void _M_range_insert(iterator __pos,
_InputIterator __first, _InputIterator __last,
input_iterator_tag); template <class _ForwardIterator>
void _M_range_insert(iterator __pos,
_ForwardIterator __first, _ForwardIterator __last,
forward_iterator_tag); }; template <class _Tp, class _Alloc>
inline bool
operator==(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
{
///元素个数同样且全部同样位置的元素值同样
return __x.size() == __y.size() &&
equal(__x.begin(), __x.end(), __y.begin());
} template <class _Tp, class _Alloc>
inline bool
operator<(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
{
///按字典序比較
return lexicographical_compare(__x.begin(), __x.end(),
__y.begin(), __y.end());
} template <class _Tp, class _Alloc>
vector<_Tp,_Alloc>&
vector<_Tp,_Alloc>::operator=(const vector<_Tp, _Alloc>& __x)
{
if (&__x != this) { ///假设是同一个对象,则不须要运行以下的操作 const size_type __xlen = __x.size();
if (__xlen > capacity()) { ///比本vector的容量还大,须要分配更大内存
iterator __tmp = _M_allocate_and_copy(__xlen, __x.begin(), __x.end()); destroy(_M_start, _M_finish); ///析构原有内存空间的对象
_M_deallocate(_M_start, _M_end_of_storage - _M_start); ///归还原有内存
_M_start = __tmp;
_M_end_of_storage = _M_start + __xlen;
}
else if (size() >= __xlen) { ///比本vecotr的元素个数还少 ///直接复制,然后析构多余对象
iterator __i = copy(__x.begin(), __x.end(), begin());
destroy(__i, _M_finish);
}
else { ///比本vector的元素个数多,单比本vector的容量小 ///此段内存已创建有对象,可直接通过copy函数调用其赋值运算符将提供的对象赋值给原有对象
copy(__x.begin(), __x.begin() + size(), _M_start); ///此段内存空白,需通过 uninitialized_copy调用其复制构造函数来创建新的对象
uninitialized_copy(__x.begin() + size(), __x.end(), _M_finish);
}
_M_finish = _M_start + __xlen;
}
return *this;
} template <class _Tp, class _Alloc>
void vector<_Tp, _Alloc>::_M_fill_assign(size_t __n, const value_type& __val)
{
if (__n > capacity()) { ///通过局部对象的创建和对象的交换完毕了内存的又一次分配和旧内存对象的析构
vector<_Tp, _Alloc> __tmp(__n, __val, get_allocator());
__tmp.swap(*this);
}
else if (__n > size()) {
fill(begin(), end(), __val);
_M_finish = uninitialized_fill_n(_M_finish, __n - size(), __val);
}
else
erase(fill_n(begin(), __n, __val), end());
} template <class _Tp, class _Alloc> template <class _InputIter>
void vector<_Tp, _Alloc>::_M_assign_aux(_InputIter __first, _InputIter __last,
input_iterator_tag) {
iterator __cur = begin(); for ( ; __first != __last && __cur != end(); ++__cur, ++__first) ///先对已有对象依次赋值
*__cur = *__first; if (__first == __last) ///赋值区间比原有区间小,删除多余元素
erase(__cur, end());
else
insert(end(), __first, __last); ///赋值区间比原有区间大,插入剩余元素,此处有可能遭遇多次内存分配
} template <class _Tp, class _Alloc> template <class _ForwardIter>
void
vector<_Tp, _Alloc>::_M_assign_aux(_ForwardIter __first, _ForwardIter __last,
forward_iterator_tag) {
size_type __len = 0;
distance(__first, __last, __len); ///通过计算赋值区间内元素个数,有计划地进行处理
if (__len > capacity()) {
iterator __tmp = _M_allocate_and_copy(__len, __first, __last);
destroy(_M_start, _M_finish);
_M_deallocate(_M_start, _M_end_of_storage - _M_start);
_M_start = __tmp;
_M_end_of_storage = _M_finish = _M_start + __len;
}
else if (size() >= __len) {
iterator __new_finish = copy(__first, __last, _M_start);
destroy(__new_finish, _M_finish);
_M_finish = __new_finish;
}
else {
_ForwardIter __mid = __first;
advance(__mid, size());
copy(__first, __mid, _M_start);
_M_finish = uninitialized_copy(__mid, __last, _M_finish);
}
} ///这个函数用来处理vector容量不足或者须要在vector非尾部插入
template <class _Tp, class _Alloc>
void
vector<_Tp, _Alloc>::_M_insert_aux(iterator __position, const _Tp& __x)
{
if (_M_finish != _M_end_of_storage) { ///vector容量足够 ///从最后一个对象開始到__position依次后移,为新插入的对象腾位置
construct(_M_finish, *(_M_finish - 1)); ///此处属空白内存,需调用复制构造函数创建对象
++_M_finish;
_Tp __x_copy = __x;
copy_backward(__position, _M_finish - 2, _M_finish - 1); ///将须要插入的值赋值给合适位置
*__position = __x_copy;
}
else { ///vector容量不足 const size_type __old_size = size();
const size_type __len = __old_size != 0 ? 2 * __old_size : 1; ///此举是为了防止多次内存分配 iterator __new_start = _M_allocate(__len);
iterator __new_finish = __new_start;
try {
__new_finish = uninitialized_copy(_M_start, __position, __new_start);
construct(__new_finish, __x);
++__new_finish;
__new_finish = uninitialized_copy(__position, _M_finish, __new_finish);
}catch(...){
///一旦失败,析构创建的对象,归还分配的内存
destroy(__new_start,__new_finish);
_M_deallocate(__new_start,__len);
} destroy(begin(), end());
_M_deallocate(_M_start, _M_end_of_storage - _M_start); _M_start = __new_start;
_M_finish = __new_finish;
_M_end_of_storage = __new_start + __len;
}
} ///实现全然同上
template <class _Tp, class _Alloc>
void
vector<_Tp, _Alloc>::_M_insert_aux(iterator __position)
{
if (_M_finish != _M_end_of_storage) {
construct(_M_finish, *(_M_finish - 1));
++_M_finish;
copy_backward(__position, _M_finish - 2, _M_finish - 1);
*__position = _Tp();
}
else {
const size_type __old_size = size();
const size_type __len = __old_size != 0 ? 2 * __old_size : 1;
iterator __new_start = _M_allocate(__len);
iterator __new_finish = __new_start;
try {
__new_finish = uninitialized_copy(_M_start, __position, __new_start);
construct(__new_finish);
++__new_finish;
__new_finish = uninitialized_copy(__position, _M_finish, __new_finish);
}catch(...){
destroy(__new_start,__new_finish);
_M_deallocate(__new_start,__len);
} destroy(begin(), end());
_M_deallocate(_M_start, _M_end_of_storage - _M_start);
_M_start = __new_start;
_M_finish = __new_finish;
_M_end_of_storage = __new_start + __len;
}
} ///在position处插入n个x
template <class _Tp, class _Alloc>
void vector<_Tp, _Alloc>::_M_fill_insert(iterator __position, size_type __n,
const _Tp& __x)
{
if (__n != 0) {
if (size_type(_M_end_of_storage - _M_finish) >= __n) { ///vector剩余容量足以容纳n个对象
_Tp __x_copy = __x;
const size_type __elems_after = _M_finish - __position;
iterator __old_finish = _M_finish; if (__elems_after > __n) { ///__position兴许元素数量多于n uninitialized_copy(_M_finish - __n, _M_finish, _M_finish); ///将后n个元素移动至finish后
_M_finish += __n; ///改动finish
copy_backward(__position, __old_finish - __n, __old_finish); ///再将__position后尚未移完的元素后移 ///至此,恰好腾出n个空间,充入就可以
fill(__position, __position + __n, __x_copy);
}
else { ///__position兴许对象数量少于n ///由于充入对象区间将超出原有区间范围,因此需分两次充入,一次是通过直接赋值充入
///一次是创建新对象充入 ///在空白内存充入__n-__elems_after个__x_copy
uninitialized_fill_n(_M_finish, __n - __elems_after, __x_copy);
_M_finish += __n - __elems_after; ///将__position后的原有对象移动到已充入对象之后
uninitialized_copy(__position, __old_finish, _M_finish);
_M_finish += __elems_after; ///在腾出的空间充入__x_copy
fill(__position, __old_finish, __x_copy);
}
}
else { ///vector剩余容量不足以容纳n个对象,需又一次分配内存 const size_type __old_size = size();
const size_type __len = __old_size + max(__old_size, __n);
iterator __new_start = _M_allocate(__len);
iterator __new_finish = __new_start;
try{
__new_finish = uninitialized_copy(_M_start, __position, __new_start);
__new_finish = uninitialized_fill_n(__new_finish, __n, __x);
__new_finish
= uninitialized_copy(__position, _M_finish, __new_finish);
}catch(...){
destroy(__new_start,__new_finish);
_M_deallocate(__new_start,__len); } destroy(_M_start, _M_finish);
_M_deallocate(_M_start, _M_end_of_storage - _M_start);
_M_start = __new_start;
_M_finish = __new_finish;
_M_end_of_storage = __new_start + __len;
}
}
} template <class _Tp, class _Alloc> template <class _InputIterator>
void
vector<_Tp, _Alloc>::_M_range_insert(iterator __pos,
_InputIterator __first,
_InputIterator __last,
input_iterator_tag)
{
///效率太低
for ( ; __first != __last; ++__first) {
__pos = insert(__pos, *__first);
++__pos;
}
} ///和_M_fill_insert大同小异
template <class _Tp, class _Alloc> template <class _ForwardIterator>
void
vector<_Tp, _Alloc>::_M_range_insert(iterator __position,
_ForwardIterator __first,
_ForwardIterator __last,
forward_iterator_tag)
{
if (__first != __last) {
size_type __n = 0;
distance(__first, __last, __n);
if (size_type(_M_end_of_storage - _M_finish) >= __n) {
const size_type __elems_after = _M_finish - __position;
iterator __old_finish = _M_finish;
if (__elems_after > __n) {
uninitialized_copy(_M_finish - __n, _M_finish, _M_finish);
_M_finish += __n;
copy_backward(__position, __old_finish - __n, __old_finish);
copy(__first, __last, __position);
}
else {
_ForwardIterator __mid = __first;
advance(__mid, __elems_after);
uninitialized_copy(__mid, __last, _M_finish);
_M_finish += __n - __elems_after;
uninitialized_copy(__position, __old_finish, _M_finish);
_M_finish += __elems_after;
copy(__first, __mid, __position);
}
}
else {
const size_type __old_size = size();
const size_type __len = __old_size + max(__old_size, __n);
iterator __new_start = _M_allocate(__len);
iterator __new_finish = __new_start;
__STL_TRY {
__new_finish = uninitialized_copy(_M_start, __position, __new_start);
__new_finish = uninitialized_copy(__first, __last, __new_finish);
__new_finish
= uninitialized_copy(__position, _M_finish, __new_finish);
}
__STL_UNWIND((destroy(__new_start,__new_finish),
_M_deallocate(__new_start,__len)));
destroy(_M_start, _M_finish);
_M_deallocate(_M_start, _M_end_of_storage - _M_start);
_M_start = __new_start;
_M_finish = __new_finish;
_M_end_of_storage = __new_start + __len;
}
}
}
大概总结一下。vector事实上就是一个动态分配的数组而已。比数组好一点的是vector在每次扩充内存的时候都会实际须要的内存多分配一些(2倍),这样降低了vector的过多的又一次分配内存。事实上vector的又一次分配内存是相当耗时的操作,由于他要对每一个原有内存中的对象运行复制构造函数调用。 除此之外,vector位于中间的删除和插入也是非常耗时的操作。由于对插入/删除后的每一个对象都要运行复制构造函数/赋值函数的调用。
STL源代码学习(vector篇)的更多相关文章
- STL源代码学习--vector用法汇总
一.容器vector 使用vector你必须包含头文件<vector>: #include<vector> 型别vector是一个定义于namespace std内的templ ...
- C++ STL源代码学习(list篇)
///STL list为双向循环链表 struct _List_node_base { _List_node_base* _M_next; _List_node_base* _M_prev; }; t ...
- C++ STL源代码学习(map,set内部heap篇)
stl_heap.h ///STL中使用的是大顶堆 /// Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap ...
- C++ STL源代码学习之算法篇
///因为篇幅太长,因此,删去了非常多接口,仅仅分析了内部实现,算法对迭代器的要求也被删去 /// search. template <class _ForwardIter1, class _F ...
- C++ STL 源代码学习(之deque篇)
stl_deque.h /** Class invariants: * For any nonsingular iterator i: * i.node is the address of an el ...
- C++STL源代码学习(之slist篇)
///stl_slist.h ///list为双向循环链表,slist为单向链表.某些操作效率更高 ///slist是SGI额外提供的单向链表,不属于C++标准 struct _Slist_node_ ...
- STL源代码剖析 读书总结
<<STL源代码剖析>> 侯捷著 非常早就买了这本书, 一直没看, 如今在实验室师兄代码的时候发现里面使用了大量泛型编程的内容, 让我有了先看看这本书的想法. 看之前我对于泛型 ...
- STL源代码分析——STL算法remove删除算法
前言 因为在前文的<STL算法剖析>中,源代码剖析许多.不方便学习,也不方便以后复习,这里把这些算法进行归类.对他们单独的源代码剖析进行解说.本文介绍的STL算法中的remove删除算法. ...
- STL源代码分析——STL算法merge合并算法
前言 因为在前文的<STL算法剖析>中.源代码剖析许多.不方便学习.也不方便以后复习,这里把这些算法进行归类.对他们单独的源代码剖析进行解说.本文介绍的STL算法中的merge合并算法. ...
随机推荐
- java分页之假分页
假分页,顾名思义,不是真正的在数据库里进行过滤,而是从数据库查询之后,取得全部结果,在展现的时候做些手脚. import java.util.ArrayList; import java.util.L ...
- Ubuntu(Linux Mint):sudo apt-get upgrade升级失败
Ubuntu上进行sudo apt-get upgrade后出现异常,升级失败. 异常信息如下: E: dpkg was interrupted, you must manually run 'dpk ...
- C++实现页码数字统计
#include<iostream> #include<iomanip> #include<cstdlib> #include<ctime> #incl ...
- Oracle性能分析1:开启SQL跟踪和获取trace文件
当Oracle查询出现效率问题时,我们往往须要了解问题所在,这样才干针对问题给出解决方式.Oracle提供了SQL运行的trace信息,当中包括了SQL语句的文本信息.一些运行统计,处理过程中的等待, ...
- PHP编译时错误解决:Don't know how to define struct flock on this system, set --enable-opcache=no
在编辑PHP5.6.1时出现了这个错误: Don't know how to define struct flock on this system, set --enable-opcache=no 解 ...
- ThinkPHP5.0框架开发--第5章 TP5.0 控制器
ThinkPHP5.0框架开发--第5章 TP5.0 控制器 第5章 TP5.0 控制器 ============================================== 上次复习 1.路 ...
- javascript系列-class2.javascript 基本使用
欢迎加入前端交流群来py: 转载请标明出处! 逻辑运算 一门计算机语言,编程的核心在于逻辑思想,当我们在编写程序的时候,逻辑是否通顺,是能否正确写出程序的关键,可以说如 ...
- Qt开发环境的搭建
首先讲讲为什么要用Qt这个东东吧!用了以后才知道,这门语言真的很不错,我权当把它当成了类库来用,Linux本身的C语言编程是很烦的,比如说串口编程,虽说C编程也不难,但是使用Qt这种封装的类库来操作的 ...
- Servlet基础(一)
JavaEE:企业级开发技术 <一.基础概念>j2ee:jdk1.1--1.4 ----->> j2ee1.1 1.2 javaee:jdk--5,6,7 ...
- 关于PageRank的总结
好久不用CSDN,最近想给带的本科生实验课开个期末习题专题页,发现CSDN的博客忽然要绑定之类.只好弃用回博客园写学习总结了.塞翁失马焉知非福. *************************** ...