deque容器是双端队列,使用前,需要添加#include <deque>
deque的内存结构如下:
根据上图可知,deque和vector,string稍有不同,deque的内存是分段连续内存结构,所以,deque的内存在增长的时候,也是分段增长的,不会像vector那样复制所有元素,然后重新分配内存,所以不存在预分配空间,所以就没有capacity函数,但是仍然存在预分配内存的情况,所以仍然有shrink_to_fit函数来使内存空间大小和元素个数相匹配。
正是由于分段增长内存,所以当一段内存中不存储deque的元素时,deque会自动将那一段内存释放。
也正是由于内存的分段,所以访问元素和使用迭代器的时候,会比vector和string稍慢(因为迭代器要在不同段的内存跳跃)
1.deque的初始化
explicit deque (const allocator_type& alloc = allocator_type());//默认构造函数,默认初始化调用
explicit deque (size_type n);//一般构造函数,创建一个含有n个元素的deque对象,元素的默认值为0或者默认对象
explicit deque (size_type n, const value_type& val,
const allocator_type& alloc = allocator_type());//一般构造函数,创建一个含有n个元素的deque对象,元素的值为val
template <class InputIterator>
deque (InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type());//使用迭代器表示的元素范围进行初始化
deque (const deque& x);//拷贝初始化
deque (const deque& x, const allocator_type& alloc);
deque (initializer_list<value_type> il,
const allocator_type& alloc = allocator_type());//列表初始化
上面的构造函数和拷贝构造函数类似list和vector
可参考博客https://blog.csdn.net/Master_Cui/article/details/107751785和https://blog.csdn.net/Master_Cui/article/details/107427911
2.deque的赋值
void assign (InputIterator first, InputIterator last);
void assign (size_type n, const value_type& val);
void assign (initializer_list<value_type> il);
类似list和vector
可参考博客https://blog.csdn.net/Master_Cui/article/details/107751785和https://blog.csdn.net/Master_Cui/article/details/107427911
reference at (size_type n);
const_reference at (size_type n) const;
reference back();
const_reference back() const;
reference front();
const_reference front() const;
由于deque的内存结构和vector与string类似,所以支持下标访问和at函数
见博客https://blog.csdn.net/Master_Cui/article/details/107427911和https://blog.csdn.net/Master_Cui/article/details/107573300
4.deque的添加
因为是双端队列,所以在头尾都可以添加元素,所以同时支持push_back和push_front
void push_back (const value_type& val);
void push_front (const value_type& val);
用法同list
deque也有insert方法
iterator insert (const_iterator position, const value_type& val);
iterator insert (const_iterator position, size_type n, const value_type& val);
template <class InputIterator>
iterator insert (const_iterator position, InputIterator first, InputIterator last);
iterator insert (const_iterator position, initializer_list<value_type> il);
用法同vector,string与list
见博客https://blog.csdn.net/Master_Cui/article/details/107427911,https://blog.csdn.net/Master_Cui/article/details/107573300,https://blog.csdn.net/Master_Cui/article/details/107751785
5.deque的删除
void pop_front();
void pop_back();
iterator erase (const_iterator position );
iterator erase (const_iterator first, const_iterator last );
用法和示意同vector,string与list
见博客https://blog.csdn.net/Master_Cui/article/details/107427911,https://blog.csdn.net/Master_Cui/article/details/107573300,https://blog.csdn.net/Master_Cui/article/details/107751785
6.deque的交换
void swap (deque& x);
同vector与list
见博客https://blog.csdn.net/Master_Cui/article/details/107427911与https://blog.csdn.net/Master_Cui/article/details/107751785
7.deque的迭代器失效
因为deque的内存结构是分段连续的,所以,除了头尾两端,在deque对象的其他位置删除,添加元素,会导致迭代器失效
void iterfailed()
{
deque<int> d1={1,2,3,4,5,6};
deque<int>::iterator it=d1.begin()+3;
d1.insert(d1.begin(), 0);
cout<<*it<<endl;
}
可见,添加元素之后,保存的迭代器失效了
示例2
void iterfailed()
{
deque<int> d1={1,2,3,4,5,6};
deque<int>::iterator it=d1.begin()+3;
d1.erase(d1.begin()+4);
cout<<*it<<endl;
}
erase同理
再就是在erase和insert后,没有更新迭代器
示例
void iterfailed()
{
deque<int> d1={1,2,3,4,5,6};
deque<int>::iterator it=d1.begin()+3;
//it=d1.erase(it);
d1.erase(it);
cout<<*it<<endl;
}
insert同理
最后就是因为逻辑不严谨,导致可能解引用尾后迭代器
示例
void iterfailed2()
{
deque<int> d1={1,2,3,4,5,6};
deque<int>::iterator it=d1.begin();
while(it!=d1.end()) {
if (*it %2==0) {
it=d1.erase(it);
}
cout<<*it<<endl;
++it;
}
}
解决办法参照博客https://blog.csdn.net/Master_Cui/article/details/107503634
因为deque不会重新分配内存,所以也就不会出现像vector和string那样重新分配内存而导致迭代器失效的情况
总之,deque迭代器失效的原因和vector类似,主要如下:
1.除了头尾两端,在deque对象的其他位置删除,添加元素,会导致迭代器失效
《C++ Primer》
http://www.cplusplus.com/reference/deque/deque/
https://www.bilibili.com/video/BV1db411q7B8?p=18
欢迎大家评论交流,作者水平有限,如有错误,欢迎指出