stl剖析之deque

本文探讨了STL中的deque容器,它是一个双向开口的连续性空间,支持头部和尾部的高效插入和删除。deque的工作原理是通过一系列小块空间连接成看似连续的存储,迭代器在空间不足时会指向新的空间并可能扩大原有空间。在进行sort操作时,deque可以通过复制到vector进行排序。deque的机制包括中控器、迭代器管理和空间动态扩展。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


/*******************************************************************************************

vector:单向开口的连续空间

deque:双向开口的连续性空间,即可以再头尾两端分别做元素的插入和删除。

两者差异:

deque允许常熟时间对起头端进行插入或者删除或移除操作,且没有所谓容量观念,因为它是动态的分段空间组合合成

因而deque没有必要保留空间。对于deque进行sort时候,可将deque完整的复制到一个vector中,然后排序后复制到deque

它的本质是什么?就是一个个小的空间连在一起 看起来如同连续的一个空间!

********************************************************************************************

那今天小雷同学就来分享一下我的见解。

个人认为,迭代器的核心就在于它是如何将空间连上?以及它是如何开辟空间的?以及它的模型是什么?

首先先看下它的整体模型:

解释:首先定义两个迭代器!一个负责pop_back,一个负责pop_front.然后开辟空间 空间一分为二!中间由_last指向。

然后起始位置就是_First(last的)指向 ,

next(last的)负责指向开辟空间中的元素位置。

_map指向中控器(就是两个int**的那个东西)。

de(队列):中的_Map直接指向中控器。

这样分析的话,双端队列其本身只负责控制中控器就可以了,而中控器(指向空间的结点)中负责指向一段空间。

迭代器负责判断、插入等一系列操作,当迭代器发现其空间不足了,那么将指向换向下一个结点。已有的空间还不足

那么,将原有的增大两倍,然后将原有的拷贝到新增的大的空间!最后释放空间!

注:deque的机理,每次拷贝或者插入值时,总会前后都预留一些空间,代码中我会注释

**********************************************************************************************************************

void push_back(const _Ty& _X)//这里是尾插定义
		{
		if (empty() || (_Last._Next == _Last._Last)) //判断空间是否为空
        {
            _Buyback(); 
            allocator.construct(_Last._Next++, _X);
        }
        else if (_Last._Next + 1 == _Last._Last)//判断空间是否到达末尾
        {
            allocator.construct(_Last._Next++, _X);
            _Buyback();
        }
        else
            allocator.construct(_Last._Next++, _X);
        ++_Size; }		

void _Buyback()
		{_Tptr _P = allocator.allocate(_DEQUESIZ, (void *)0);
		if (empty())
			{_Mapsize = _DEQUEMAPSIZ;
			size_type _N = _Mapsize / 2;
			_Getmap();
			_Setptr(_Map + _N, _P);
			_First = iterator(_P + _DEQUESIZ / 2, _Map + _N);
			_Last = _First; }
		else if (_Last._Map < _Map + (_Mapsize - 1))
			{_Setptr(++_Last._Map, _P);
			_Last = iterator(_P, _Last._Map); }
		else
			{difference_type _I = _Last._Map - _First._Map + 1;//这里是队列的指向尾头
			_Mapptr _M = _Growmap(2 * _I);
			_Setptr(_M + _I, _P);
			_First = iterator(_First._Next, _M);
			_Last = iterator(_P, _M + _I); }}

_Mapptr _Growmap(size_type _Newsize)
		{_Mapptr _M = (_Mapptr)allocator._Charalloc(
			_Newsize * sizeof (_Tptr));
		copy(_First._Map, _Last._Map + 1,
			_M + _Newsize / 4);//注意这里往后加了位置
		allocator.deallocate(_Map, _Mapsize);//释放原来了
		_Map = _M;   //新的指向
		_Mapsize = _Newsize;//新的大小
		return (_M + _Newsize / 4); }


*******************************************************************************************************************************************************


源码:

#if     _MSC_VER > 1000
#pragma once
#endif

#ifndef _DEQUE_
#define _DEQUE_
#include <iterator>
#include <memory>
#include <stdexcept>
#include <xutility>

#ifdef  _MSC_VER
#pragma pack(push,8)
#endif  /* _MSC_VER */
_STD_BEGIN
#define _DEQUEMAPSIZ	2
#define _DEQUESIZ (4096 < sizeof (_Ty) ? 1 : 4096 / sizeof (_Ty)) //定义初始空间大小
		// TEMPLATE CLASS deque
template<class _Ty, class _A = allocator<_Ty> >
	class deque {
public:
	typedef deque<_Ty, _A> _Myt;     //这里都是重命名
	typedef _A allocator_type;
	typedef _A::size_type size_type;
	typedef _A::difference_type difference_type;
	typedef _A::pointer _Tptr;
	typedef _A::const_pointer _Ctptr;
	typedef _POINTER_X(_Tptr, _A) _Mapptr;
	typedef _A::reference reference;
	typedef _A::const_reference const_reference;
	typedef _A::value_type value_type;
		// CLASS const_iterator
	class iterator;
	class const_iterator : public _Ranit<_Ty, difference_type> {
	public:
		friend class deque<_Ty, _A>;
		const_iterator()
			: _First(0), _Last(0), _Next(0), _Map(0) {}//迭代器初始化
		const_iterator(_Tptr _P, _Mapptr _M)
			: _First(*_M), _Last(*_M + _DEQUESIZ),
				_Next(_P), _Map(_M) {}
		const_iterator(const iterator& _X)
			: _First(_X._First), _Last(_X._Last), _Next(_X._Next), //这是它的指向
			  _Map(_X._Map) {}
		const_reference operator*() const
			{return (*_Next); }
		_Ctptr operator->() const
			{return (&**this); }
		const_iterator& operator++()
			{if (++_Next == _Last)
				{_First = *++_Map;
				_Last = _First + _DEQUESIZ;
				_Next = _First; }
			return (*this); }
		const_iterator operator++(int)
			{const_iterator _Tmp = *this;
			++*this;
			return (_Tmp); }
		const_iterator& operator--()
			{if (_Next == _First)
				{_First = *--_Map;
				_Last = _First + _DEQUESIZ;
				_Next = _Last; }
			--_Next;
			return (*this); }
		const_iterator operator--(int)
			{const_iterator _Tmp = *this;
			--*this;
			return (_Tmp); }
		const_iterator& operator+=(difference_type _N)
			{_Add(_N);
			return (*this); }
		const_iterator& operator-=(difference_type _N)
			{return (*this += -_N); }
		const_iterator operator+(difference_type _N) const
			{const_iterator _Tmp = *this;
			return (_Tmp += _N); }
		const_iterator operator-(difference_type _N) const
			{const_iterator _Tmp = *this;
			return (_Tmp -= _N); }
		difference_type operator-(const const_iterator& _X) const
			{return (_Map == _X._Map ? _Next - _X._Next
				: _DEQUESIZ * (_Map - _X._Map - 1)
				+ (_Next - _First) + (_X._Last - _X._Next)); }
		const_reference operator[](difference_type _N) const
			{return (*(*this + _N)); }
		bool operator==(const const_iterator& _X) const
			{return (_Next == _X._Next); }
		bool operator!=(const const_iterator& _X) const
			{return (!(*this == _X)); }
		bool operator<(const const_iterator& _X) const
			{return (_Map < _X._Map
				|| _Map == _X._Map && _Next < _X._Next); }
		bool operator<=(const const_iterator& _X) const
			{return (!(_X < *this)); }
		bool operator>(const const_iterator& _X) const
			{return (_X < *this); }
		bool operator>=(const const_iterator& _X) const
			{return (!(*this < _X)); }
	protected:
		void _Add(difference_type _N)
			{difference_type _Off = _N + _Next - _First;
			difference_type _Moff = (0 <= _Off)
				? _Off / _DEQUESIZ
				: -((_DEQUESIZ - 1 - _Off) / _DEQUESIZ);
			if (_Moff == 0)
				_Next += _N;
			else
				{_Map += _Moff;
				_First = *_Map;
				_Last = _First + _DEQUESIZ;
				_Next = _First + (_Off - _Moff * _DEQUESIZ); }}
	_PROTECTED:
		_Tptr _First, _Last, _Next;
		_Mapptr _Map;
		};
		// CLASS iterator
	class iterator : public const_iterator {
	public:
		iterator()
			{}
		iterator(_Tptr _P, _Mapptr _M)
			: const_iterator(_P, _M) {}
		reference operator*() const
			{return (*_Next); }
		_Tptr operator->() const
			{return (&**this); }
		iterator& operator++()
			{if (++_Next == _Last)
				{_First = *++_Map;
				_Last = _First + _DEQUESIZ;
				_Next = _First; }
			return (*this); }
		iterator operator++(int)
			{iterator _Tmp = *this;
			++*this;
			return (_Tmp); }
		iterator& operator--()
			{if (_Next == _First)
				{_First = *--_Map;
				_Last = _First + _DEQUESIZ;
				_Next = _Last; }
			--_Next;
			return (*this); }
		iterator operator--(int)
			{iterator _Tmp = *this;
			--*this;
			return (_Tmp); }
		iterator& operator+=(difference_type _N)
			{_Add(_N);
			return (*this); }
		iterator& operator-=(difference_type _N)
			{return (*this += -_N); }
		iterator operator+(difference_type _N) const
			{iterator _Tmp = *this;
			return (_Tmp += _N); }
		iterator operator-(difference_type _N) const
			{iterator _Tmp = *this;
			return (_Tmp -= _N); }
		difference_type operator-(const iterator& _X) const
			{return (_Map == _X._Map ? _Next - _X._Next
				: _DEQUESIZ * (_Map - _X._Map - 1)
				+ (_Next - _First) + (_X._Last - _X._Next)); }
		reference operator[](difference_type _N) const
			{return (*(*this + _N)); }
		bool operator==(const iterator& _X) const
			{return (_Next == _X._Next); }
		bool operator!=(const iterator& _X) const
			{return (!(*this == _X)); }
		bool operator<(const iterator& _X) const
			{return (_Map < _X._Map
				|| _Map == _X._Map && _Next < _X._Next); }
		bool operator<=(const iterator& _X) const
			{return (!(_X < *this)); }
		bool operator>(const iterator& _X) const
			{return (_X < *this); }
		bool operator>=(const iterator& _X) const
			{return (!(*this < _X)); }
		};
	typedef reverse_iterator<const_iterator, value_type,
		const_reference, _Ctptr, difference_type>
			const_reverse_iterator;
	typedef reverse_iterator<iterator, value_type,
		reference, _Tptr, difference_type>
			reverse_iterator;
	explicit deque(const _A& _Al = _A())
		: allocator(_Al),
			_First(), _Last(), _Map(0), _Mapsize(0), _Size(0)
		{}
	explicit deque(size_type _N, const _Ty& _V = _Ty(),
		const _A& _Al = _A())
		: allocator(_Al),
			_First(), _Last(), _Map(0), _Mapsize(0), _Size(0)
		{insert(begin(), _N, _V); }
	deque(const _Myt& _X)
		: allocator(_X.allocator),
			_First(), _Last(), _Map(0), _Mapsize(0), _Size(0)
		{copy(_X.begin(), _X.end(), back_inserter(*this)); }
	typedef const_iterator _It;
		deque(_It _F, _It _L, const _A& _Al = _A())
		: allocator(_Al),
			_First(), _Last(), _Map(0), _Mapsize(0), _Size(0)
		{copy(_F, _L, back_inserter(*this)); }
	~deque()
		{while (!empty())
			pop_front(); }
	_Myt& operator=(const _Myt& _X)
		{if (this != &_X)
			{iterator _S;
			if (_X.size() <= size())
				{_S = copy(_X.begin(), _X.end(), begin());
				erase(_S, end()); }
			else
				{const_iterator _Sx = _X.begin() + size();
				_S = copy(_X.begin(), _Sx, begin());
				copy(_Sx, _X.end(), inserter(*this, _S)); }}
		return (*this); }
	iterator begin()
		{return (_First); }
	const_iterator begin() const
		{return ((const_iterator)_First); }
	iterator end()
		{return (_Last); }
	const_iterator end() const
		{return ((const_iterator)_Last); }
	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())); }
	void resize(size_type _N, _Ty _X = _Ty())
		{if (size() < _N)
			insert(end(), _N - size(), _X);
		else if (_N < size())
			erase(begin() + _N, end()); }
	size_type size() const
		{return (_Size); }
	size_type max_size() const
		{return (allocator.max_size()); }
	bool empty() const
		{return (size() == 0); }
	_A get_allocator() const
		{return (allocator); }
	const_reference at(size_type _P) const
		{if (size() <= _P)
			_Xran();
		return (*(begin() + _P)); }
	reference at(size_type _P)
		{if (size() <= _P)
			_Xran();
		return (*(begin() + _P)); }
	const_reference operator[](size_type _P) const
		{return (*(begin() + _P)); }
	reference operator[](size_type _P)
		{return (*(begin() + _P)); }
	reference front()
		{return (*begin()); }
	const_reference front() const
		{return (*begin()); }
	reference back()
		{return (*(end() - 1)); }
	const_reference back() const
		{return (*(end() - 1)); }
	void push_front(const _Ty& _X)
		{if (empty() || _First._Next == _First._First)
			_Buyfront();
		allocator.construct(--_First._Next, _X);
		++_Size; }
	void pop_front()
		{allocator.destroy(_First._Next++);
		--_Size;
		if (empty() || _First._Next == _First._Last)
			_Freefront(); }
	void push_back(const _Ty& _X)
		{
		if (empty() || (_Last._Next == _Last._Last))
        {
            _Buyback();
            allocator.construct(_Last._Next++, _X);
        }
        else if (_Last._Next + 1 == _Last._Last)
        {
            allocator.construct(_Last._Next++, _X);
            _Buyback();
        }
        else
            allocator.construct(_Last._Next++, _X);
        ++_Size; }
	void pop_back()
		{
        if (_Last._Next == _Last._First)
			_Freeback();
		if (!empty())
			allocator.destroy(--_Last._Next);
		--_Size;
		if (empty())
			_Freeback(); }
	void assign(_It _F, _It _L)
		{erase(begin(), end());
		insert(begin(), _F, _L); }
	void assign(size_type _N, const _Ty& _X = _Ty())
		{erase(begin(), end());
		insert(begin(), _N, _X); }
	iterator insert(iterator _P, const _Ty& _X = _Ty())
		{if (_P == begin())
			{push_front(_X);
			return (begin()); }
		else if (_P == end())
			{push_back(_X);
			return (end() - 1); }
		else
			{iterator _S;
			size_type _Off = _P - begin();
			if (_Off < size() / 2)
				{push_front(front());
				_S = begin() + _Off;
				copy(begin() + 2, _S + 1, begin() + 1); }
			else
				{push_back(back());
				_S = begin() + _Off;
				copy_backward(_S, end() - 2, end() - 1); }
			*_S = _X;
			return (_S); }}
	void insert(iterator _P, size_type _M, const _Ty& _X)
		{iterator _S;
		size_type _I;
		size_type _Off = _P - begin();
		size_type _Rem = _Size - _Off;
		if (_Off < _Rem)
			if (_Off < _M)
				{for (_I = _M - _Off; 0 < _I; --_I)
					push_front(_X);
				for (_I = _Off; 0 < _I; --_I)
					push_front(begin()[_M - 1]);
				_S = begin() + _M;
				fill(_S, _S + _Off, _X); }
			else
				{for (_I = _M; 0 < _I; --_I)
					push_front(begin()[_M - 1]);
				_S = begin() + _M;
				copy(_S + _M, _S + _Off, _S);
				fill(begin() + _Off, _S + _Off, _X); }
		else
			if (_Rem < _M)
				{for (_I = _M - _Rem; 0 < _I; --_I)
					push_back(_X);
				for (_I = 0; _I < _Rem; ++_I)
					push_back(begin()[_Off + _I]);
				_S = begin() + _Off;
				fill(_S, _S + _Rem, _X); }
			else
				{for (_I = 0; _I < _M; ++_I)
					push_back(begin()[_Off + _Rem - _M + _I]);
				_S = begin() + _Off;
				copy_backward(_S, _S + _Rem - _M, _S + _Rem);
				fill(_S, _S + _M, _X); }}
	void insert(iterator _P, _It _F, _It _L)
		{size_type _M = 0;
		_Distance(_F, _L, _M);
		size_type _I;
		size_type _Off = _P - begin();
		size_type _Rem = _Size - _Off;
		if (_Off < _Rem)
			if (_Off < _M)
				{_It _Qx = _F;
				advance(_Qx, _M - _Off);
				for (_It _Q = _Qx; _F != _Q; )
					push_front(*--_Q);
				for (_I = _Off; 0 < _I; --_I)
					push_front(begin()[_M - 1]);
				copy(_Qx, _L, begin() + _M); }
			else
				{for (_I = _M; 0 < _I; --_I)
					push_front(begin()[_M - 1]);
				iterator _S = begin() + _M;
				copy(_S + _M, _S + _Off, _S);
				copy(_F, _L, begin() + _Off); }
		else
			if (_Rem < _M)
				{_It _Qx = _F;
				advance(_Qx, _Rem);
				for (_It _Q = _Qx; _Q != _L; ++_Q)
					push_back(*_Q);
				for (_I = 0; _I < _Rem; ++_I)
					push_back(begin()[_Off + _I]);
				copy(_F, _Qx, begin() + _Off); }
			else
				{for (_I = 0; _I < _M; ++_I)
					push_back(begin()[_Off + _Rem - _M + _I]);
				iterator _S = begin() + _Off;
				copy_backward(_S, _S + _Rem - _M, _S + _Rem);
				copy(_F, _L, _S); }}
	iterator erase(iterator _P)
		{return (erase(_P, _P + 1)); }
	iterator erase(iterator _F, iterator _L)
		{size_type _N = _L - _F;
		size_type _M = _F - begin();
		if (_M < end() - _L)
			{copy_backward(begin(), _F, _L);
			for (; 0 < _N; --_N)
				pop_front(); }
		else
			{copy(_L, end(), _F);
			for (; 0 < _N; --_N)
				pop_back(); }
		return (_M == 0 ? begin() : begin() + _M); }
	void clear()
		{erase(begin(), end()); }
	void swap(_Myt& _X)
		{if (allocator == _X.allocator)
			{std::swap(_First, _X._First);
			std::swap(_Last, _X._Last);
			std::swap(_Map, _X._Map);
			std::swap(_Mapsize, _X._Mapsize);
			std::swap(_Size, _X._Size); }
		else
			{_Myt _Ts = *this; *this = _X, _X = _Ts; }}
	friend void swap(_Myt& _X, _Myt& _Y)
		{_X.swap(_Y); }
protected:
	void _Buyback()
		{_Tptr _P = allocator.allocate(_DEQUESIZ, (void *)0);
		if (empty())
			{_Mapsize = _DEQUEMAPSIZ;
			size_type _N = _Mapsize / 2;
			_Getmap();
			_Setptr(_Map + _N, _P);
			_First = iterator(_P + _DEQUESIZ / 2, _Map + _N);
			_Last = _First; }
		else if (_Last._Map < _Map + (_Mapsize - 1))
			{_Setptr(++_Last._Map, _P);
			_Last = iterator(_P, _Last._Map); }
		else
			{difference_type _I = _Last._Map - _First._Map + 1;
			_Mapptr _M = _Growmap(2 * _I);
			_Setptr(_M + _I, _P);
			_First = iterator(_First._Next, _M);
			_Last = iterator(_P, _M + _I); }}
	void _Buyfront()
		{_Tptr _P = allocator.allocate(_DEQUESIZ, (void *)0);
		if (empty())
			{_Mapsize = _DEQUEMAPSIZ;
			size_type _N = _Mapsize / 2;
			_Getmap();
			_Setptr(_Map + _N, _P);
			_First = iterator(_P + (_DEQUESIZ / 2 + 1),
				_Map + _N);
			_Last = _First; }
		else if (_Map < _First._Map)
			{_Setptr(--_First._Map, _P);
			_First = iterator(_P + _DEQUESIZ, _First._Map); }
		else if (_Last._Map == _First._Map)
			{_Setptr(_Last._Map++, *_First._Map);
			_Setptr(_First._Map+1, *_First._Map);
			_Setptr(_First._Map, _P);
			_First = iterator(_P + _DEQUESIZ, _First._Map); }
		else
			{difference_type _I = _Last._Map - _First._Map + 1;
			_Mapptr _M = _Growmap(2 * _I);
			_Setptr(--_M, _P);
			_First = iterator(_P + _DEQUESIZ, _M);
			_Last = iterator(_Last._Next, _M + _I); }}
	void _Freeback()
		{_Freeptr(_Last._Map--);
		if (empty())
			{if (_First._Map == _Last._Map)
                _Freeptr(_First._Map);
			_First = iterator();
			_Last = _First;
			_Freemap(); }
		else
			_Last = iterator(*_Last._Map + _DEQUESIZ,
				_Last._Map); }
	void _Freefront()
		{_Freeptr(_First._Map++);
		if (empty())
			{_First = iterator();
			_Last = _First;
			_Freemap(); }
		else
			_First = iterator(*_First._Map, _First._Map); }
	void _Xran() const
		{_THROW(out_of_range, "invalid deque<T> subscript"); }
	void _Freemap()
		{allocator.deallocate(_Map, _Mapsize); }
	void _Freeptr(_Mapptr _M)
		{allocator.deallocate(*_M, _DEQUESIZ); }
	void _Getmap()
		{_Map = (_Mapptr)allocator._Charalloc(
			_Mapsize * sizeof (_Tptr)); }
	_Mapptr _Growmap(size_type _Newsize)
		{_Mapptr _M = (_Mapptr)allocator._Charalloc(
			_Newsize * sizeof (_Tptr));
		copy(_First._Map, _Last._Map + 1,
			_M + _Newsize / 4);
		allocator.deallocate(_Map, _Mapsize);
		_Map = _M;
		_Mapsize = _Newsize;
		return (_M + _Newsize / 4); }
	void _Setptr(_Mapptr _M, _Tptr _P)
		{*_M = _P; }
	_A allocator;
	iterator _First, _Last;
	_Mapptr _Map;
	size_type _Mapsize, _Size;
	};
		// deque TEMPLATE OPERATORS
template<class _Ty, class _A> inline
	bool operator==(const deque<_Ty, _A>& _X,
		const deque<_Ty, _A>& _Y)
	{return (_X.size() == _Y.size()
		&& equal(_X.begin(), _X.end(), _Y.begin())); }
template<class _Ty, class _A> inline
	bool operator!=(const deque<_Ty, _A>& _X,
		const deque<_Ty, _A>& _Y)
	{return (!(_X == _Y)); }
template<class _Ty, class _A> inline
	bool operator<(const deque<_Ty, _A>& _X,
		const deque<_Ty, _A>& _Y)
	{return (lexicographical_compare(_X.begin(), _X.end(),
		_Y.begin(), _Y.end())); }
template<class _Ty, class _A> inline
	bool operator<=(const deque<_Ty, _A>& _X,
		const deque<_Ty, _A>& _Y)
	{return (!(_Y < _X)); }
template<class _Ty, class _A> inline
	bool operator>(const deque<_Ty, _A>& _X,
		const deque<_Ty, _A>& _Y)
	{return (_Y < _X); }
template<class _Ty, class _A> inline
	bool operator>=(const deque<_Ty, _A>& _X,
		const deque<_Ty, _A>& _Y)
	{return (!(_X < _Y)); }
_STD_END
#ifdef  _MSC_VER
#pragma pack(pop)
#endif  /* _MSC_VER */

#endif /* _DEQUE_ */

/*
 * Copyright (c) 1995 by P.J. Plauger.  ALL RIGHTS RESERVED. 
 * Consult your license regarding permissions and restrictions.
 */

/*
 * This file is derived from software bearing the following
 * restrictions:
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Permission to use, copy, modify, distribute and sell this
 * software and its documentation for any purpose is hereby
 * granted without fee, provided that the above copyright notice
 * appear in all copies and that both that copyright notice and
 * this permission notice appear in supporting documentation.
 * Hewlett-Packard Company makes no representations about the
 * suitability of this software for any purpose. It is provided
 * "as is" without express or implied warranty.
 */


### C++ STL `deque` 使用方法及特性 #### 一、基本概念 `std::deque<T>` 是标准模板库(STL)提供的一种双端队列容器,支持快速的随机访问以及高效的两端插入和删除操作。这种灵活性使得它适用于多种场景下的数据存储需求。 #### 二、主要功能与使用方式 ##### (一)创建与初始化 可以像其他STL容器一样通过默认构造函数来实例化一个空的`deque`对象;也可以指定初始大小或填充特定数量相同类型的元素进行初始化[^4]。 ```cpp // 创建一个整型dequeue,默认无参数则为空 std::deque<int> myDeque; // 初始化含有五个零值整数的dequeue std::deque<int> anotherDeque(5, 0); ``` ##### (二)元素存取 提供了`front()`获取头部元素引用,`back()`获得尾部元素引用的方法。对于任意位置上的元素,则可以直接利用下标运算符[]来进行读写操作。 ```cpp myDeque.push_back(1); // 向后追加新项 anotherDeque.front(); // 访问第一个元素 anotherDeque.back(); // 获取最后一个元素 anotherDeque[2]; // 索引第三个元素 (假设存在) ``` ##### (三)增删改查 - 插入:除了常规的`push_back()/push_front()`外,在C++20版本之后还增加了更灵活的方式——`emplace_*`系列成员函数允许直接在目标地点构建对象而无需先创建临时变量再转移所有权[^3]; - 删除:不仅能够分别针对前后两端调用`pop_back()/pop_front()`移除单个节点,还可以借助于新增API如`erase_if()`批量清除符合条件的所有条目[^1]; - 修改:可通过迭代器配合算法库中的工具完成复杂变换任务,比如下面的例子展示了如何将每一个数值翻倍处理[^2]: ```cpp std::for_each(myDeque.begin(), myDeque.end(), [](int& elem){ elem *= 2; }); ``` ##### (四)查询统计 为了方便开发者判断当前状态,内置了一些辅助性的属性接口,例如检测是否为空(`empty()`)或是计算总长度(`size()`)等. #### 三、内部结构特点分析 不同于连续内存布局的传统数组向量(vector),`deque`采用了分段式的管理策略,即将整个序列分割成若干固定大小的小块(block),每一块之间保持一定间隔以便后续扩展时能更容易找到合适的位置安插新的片段而不至于频繁触发大规模重定位动作。这样的设计既保留了一定程度上类似于链表那样动态调整的优势,又兼顾到了接近线性寻址所带来的性能提升效果. #### 四、适用范围对比总结 当面对需要频繁执行双向末端更新且偶尔涉及中间部分修改的应用场合时,选用`deque`往往可以获得更好的综合表现。然而值得注意的是由于其特殊的组织形式可能会造成缓存命中率下降进而影响到某些情况下顺序扫描效率,所以在实际项目选型过程中应当权衡利弊做出合理抉择.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值