最近有个开发需求,根据server传递来的广告位来展示某条广告。

但最终存储广告的数据结构是deque,里面存储的东西还是对象(stl 基于拷贝语义)。

想了半天,在开头和结尾插入比较方便,在中间插入就有些困难了——因为是双端队列,思维惯性啊!

另外一个问题deque中存储的是对象,这个涉及到覆盖和新的拷贝问题,如果对象很大(这就是现实),那会影响性能。

网上

但是产品需要摆在那边,没办法需要实现啊,只能在可能的情况下,尽量减少拷贝。

于是想到如果插入位置在deque的前半部分,就对deque的前半部分进行操作(pop_front等),如果在deque的后半部分,

就在deque的后半部分(push_back())进行操作。

实现的过程中,有些接口忘了,去cppreference.com 上去查deque的接口,发现deque有insert接口——当时就崩溃了,有木有!!!

http://en.cppreference.com/w/cpp/container/deque/insert

iterator insert( iterator pos, const T& value );

于是直接调用接口就好了,STL的实现比直接造的轮子好!!!!

但这个不是结束,为什么deque会提供insert接口,它怎么实现的,是否会避免一些数据的拷贝?带着这个问题,我查看了下4.1.2的源码。

template <typename _Tp, typename _Alloc>
typename deque<_Tp, _Alloc>::iterator
deque<_Tp, _Alloc>::
insert(iterator position, const value_type& __x)
{
if (position._M_cur == this->_M_impl._M_start._M_cur)
{
push_front(__x);
return this->_M_impl._M_start;
}
else if (position._M_cur == this->_M_impl._M_finish._M_cur)
{
push_back(__x);
iterator __tmp = this->_M_impl._M_finish;
--__tmp;
return __tmp;
}
else
return _M_insert_aux(position, __x);
}

可以看到这个函数,先判断了pos的位置,如果在前面插入,则调用push_front,如果在末尾插入,则调用push_back。

我们关注的在中间插入,走向了_M_insert_aux函数。

template <typename _Tp, typename _Alloc>
typename deque<_Tp, _Alloc>::iterator
deque<_Tp, _Alloc>::
_M_insert_aux(iterator __pos, const value_type& __x)
{
difference_type __index = __pos - this->_M_impl._M_start;
value_type __x_copy = __x; // XXX copy
if (static_cast<size_type>(__index) < size() / 2)
{
push_front(front());

iterator __front1 = this->_M_impl._M_start;
++__front1;
iterator __front2 = __front1;
++__front2;
__pos = this->_M_impl._M_start + __index;
iterator __pos1 = __pos;
++__pos1;
std::copy(__front2, __pos1, __front1);
} 。。。。。

这个的实现,与我们当时的设想很类似,即看插入的位置与中间元素的关系,如果在前面,则push_front,否则push_back

总结1. STL的人很有爱(某人说的),这个接口都提供了,而且实现效率还可以。

2. STL的接口文档需要经常看看,避免造轮子。

deque 居然已经实现了 insert 接口的更多相关文章

  1. Spring中毒太深,离开Spring我居然连最基本的接口都不会写了

    前言 随着 Spring 的崛起以及其功能的完善,现在可能绝大部分项目的开发都是使用 Spring(全家桶) 来进行开发,Spring也确实和其名字一样,是开发者的春天,Spring 解放了程序员的双 ...

  2. Spring中毒太深,离开了Spring,我居然连最基本的接口都不会写了¯\_(ツ)_/¯

    前言 众所周知,Java必学的框架其中就是SSM,Spring已经融入了每个开发人员的生活,成为了不可或缺的一份子. 随着 Spring 的崛起以及其功能的完善,现在可能绝大部分项目的开发都是使用 S ...

  3. deque源码4(deque元素操作:pop_back、pop_front、clear、erase、insert)

    deque源码1(deque概述.deque中的控制器) deque源码2(deque迭代器.deque的数据结构) deque源码3(deque的构造与内存.ctor.push_back.push_ ...

  4. java三篇博客转载 详解-vector,stack,queue,deque

    博客一:转载自http://shmilyaw-hotmail-com.iteye.com/blog/1825171 java stack的详细实现分析 简介 我们最常用的数据结构之一大概就是stack ...

  5. 在VMware 虚拟机中配置 windows2003系统的NLB负载均衡;0x800706D5错误的解决方法;没有接口可用于安装新的群集

    首先在VM里面 我装了3个2003的系统,  分别为 webservice01 ,webservice 02 , 以及   webview 这3台. 前面两台用于配置负载均衡,后面的webview就是 ...

  6. Java中的queue和deque对比详解

    队列(queue)简述 队列(queue)是一种常用的数据结构,可以将队列看做是一种特殊的线性表,该结构遵循的先进先出原则.Java中,LinkedList实现了Queue接口,因为LinkedLis ...

  7. JAVA集合接口及类

    各接口及类关系图 Iterable 所有集合的初始接口,实现该接口可进行foreach操作,只有一个iterator()方法,并返回iterator类型: Iterable在java.lang下,It ...

  8. Deque(队列)

    目录 Deque 概述 特点 常用方法 双向队列操作 ArrayDeque Deque 概述 一个线性 collection,支持在两端插入和移除元素.名称 deque 是"double e ...

  9. STL deque用法

    Deque 容器 deque容器是C++标准模版库(STL,Standard Template Library)中的部分内容.deque容器类与vector类似,支持随机访问和快速插入删除,它在容器中 ...

随机推荐

  1. sdut2164Binomial Coeffcients(组合数求模)

    http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2164 贴一篇写组合数求mod比较好的帖子 这里 ...

  2. Asp.Net生命周期系列四

    上回我们说的当一个Http请求来到HttpModule这里的时候,Asp.Net内部并未对这个Http请求做出任何的处理,我们可以对这个Http请求添加一些我们需要的信息,以方便我们控制这个Http请 ...

  3. hdu4618 Palindrome Sub-Array dp+记忆化搜索 或者直接暴力

    题意就是找一个 左右上下对称的正方形矩阵. 连接:http://acm.hdu.edu.cn/showproblem.php?pid=4618 没想到记忆+dp和暴力就能水过... //记忆话搜索+d ...

  4. POJ2886 Who Gets the Most Candies? 线段树 反素数

    题意:有一群小朋友围成一个环,编号1,2,3…N.每个人手上握着一个非0的数字,首先第K个人出列,然后看他手上的数字,假设为m,则从下一个开始第m个人出列,一直如此.并设i为小于等于N的最大反素数,问 ...

  5. Replication in Kafka

    Replication简介 Kafka中的Replication功能是为了给每个partition提供备份,当某个Broker挂掉时可以迅速实现故障切换(failover).我们可以在创建或修改top ...

  6. UIPikerView

    UIPikerView的属性 1.   numberOfComponents:返回UIPickerView当前的列数 NSInteger num = _pickerView.numberOfCompo ...

  7. (转)UILabel的详细使用

    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 75, 40)];   //初始化UIlbel并设定frame lab ...

  8. ANDROID5.0触摸屏校准

    1.校准原理: 1)首先生成校准用的参数,可以适用tslib生成校准参数,也可以使用校准app生成:使用校准app进行校准对使用者要求比较低,使用者可以不用学习复杂的命令:本文使用app方式 2)生成 ...

  9. Javascript模块化编程(三):require.js的用法 (转)

    转自:http://my.oschina.net/u/1390066/blog/213769 一.为什么要用require.js? 最早的时候,所有Javascript代码都写在一个文件里面,只要加载 ...

  10. ViewPager 滑动页(四)

    需求:在ViewPager 滑动页(三) 基础上,减少界面层级. 效果图: 图层数变更前: 图层数变更后: 主要代码实现: <?xml version="1.0" encod ...