青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

3d Game Walkman

3d圖形渲染,網絡引擎 — tonykee's Blog
隨筆 - 45, 文章 - 0, 評論 - 309, 引用 - 0
數據加載中……

今天找到一個不得不用deque的理由

過去總以為vector和deque差不多,效率方面deque和vector接近,那干脆用效率高的vector好了。
但我忽略了另一方,一個事務存在就有它的理由,今天找到程序里面隱藏的bug給了我不得不用deque的理由,
deque和vector的結構很類似,但它是多段連續空間,如果vector空間不夠的時候,要重新分配空間,并把所有的數據復制到新的空間中去,
deque不會這么做,它會去另外開辟一塊連續空間去存放數據,所以存儲效率方面deque高于vector,但deque又不同于鏈表,它可以說是順序存儲結構和鏈式存儲結構的一個折中方案把,今天我寫了段代碼,是這樣的結構

vector<SerializedEntity> archiveEntities; //也許你要問問什么不用vector<SerializedEntity*>,我這里比較特別,因為要讀寫磁盤的數據,序列化存儲                                            //回避了指針的數據讀寫方式,所以用的vector<SerializedEntity>
那么:Entity * ent = &archive[0];          //看似沒問題,其實里面暗藏殺機
這個archiveEntities 如果不改變是沒有問題,但如果序列集又動態添加了數據,恰好沒有預留空間,那么將導致整個集合重新分配連續空間了,所以那個引用也將“失效了”,這讓我很頭疼,這個時候讓我想起了deque,它真的很棒,不會去重整空間,需要的時候再開辟其他連續的空間,雖然讀的效率降低了,但
這點損失對于我的程序基本可以忽略不計的,IO數據本身就很少去遍歷訪問,卻能給程序很好的去“引用”,不用擔心引用失效的情況,這方面deque確實是個很好的選擇
找到一篇文章與大家分享一下,也是應證我的觀點的:

operator[]

  operator[] 是指通過下標取數據。顯然 list 的復雜度為O(N),非常慢。而 vector、deque 均為 O(1)。讓我們想象下 deque::operator[] 的實現:

 

 _E deque::operator[](int i)
{
  return m_storage[i/BlockSize][i%BlockSize];
} 

 

  可以看出,deque 只比 vector 多了一次內存訪問。

  空間性能分析

  push_back

  vector

  很不幸,如果 vector 采用 N*2 的內存增長模型(通常如此),那么在最差的情況下,空間復雜度就是 2*N ,最好的情況下為 N(所有的內存都用上了)。平均來講,空間復雜度為 1.5*N .也就是說,通常差不多有一半的內存是被浪費的。

  list

  list 的空間浪費與 vector 相比不遑多讓。它的空間復雜度為 (1 + sizeof(pointer)*2/sizeof(_E))*N.如果我們讓 list 存儲的元素為 pointer(即 _E = pointer),那么空間復雜度為 3*N,比 vector 還浪費。

  deque

  deque 的最差情況下的空間復雜度為 N + sizeof(pointer)*2*N/(BlockSize*sizeof(_E))(這里假設vector也采用 2*N 增長模型,平均復雜度則將式中2改為1.5即可)。如果我們保存的元素為 pointer(即 _E = pointer),并且BlockSize取512,那么空間復雜度為 N + N/256.也就是說最差情況下只浪費了 N/256 的內存。

  deque的其他特性

  元素地址不變

  由于 deque 并不進行數據搬移,帶來一個有意思的特性,就是 deque 的元素地址在只有 push_back/push_front,沒有 insert/erase 時,可保持元素地址不變。

  需要注意的是,vector 并不具備這樣的特性。如下的代碼是不合法的:

 

std::vector<int> vec;
...
int& elem = vec[i];
vec.push_back(100);
elem = 99; // error: can't access elem since vec was changed! 

 

  由于取得 elem 之后存在 push_back 操作,所獲得的元素地址(&elem)可能會由于內存搬移而失效。但是如果我們將容器換為 std::deque,則這個代碼不會有任何問題。

 

 std::deque<int> dq;
...
int& elem = dq[i];
dq.push_back(100);
elem = 99; // ok! 

 

  另外需要注意的是,元素地址不變,并不代表 iterator 不變,如下的代碼 deque 并不支持:

 

std::deque<int> dq;
...
std::deque<int>::iterator it = dq.begin() + i;
dq.push_back(100);
*it = 99; // error: can't access iterator since deque was changed!

 

  結論

  通過 vector, list, deque 的時間、空間性能對比,我們可以看出,應該提倡盡可能使用 deque 這個容器。特別是,如果要承受海量數據,deque 是最合適的人選了。


posted on 2009-05-24 13:25 李侃 閱讀(8323) 評論(15)  編輯 收藏 引用 所屬分類: 雜談

評論

# re: 今天找到一個不得不用deque的理由[未登錄]  回復  更多評論   

只能說你對vector沒有認識清楚而以,一般也都使用iterator
2009-05-24 13:36 | 關中刀客

# re: 今天找到一個不得不用deque的理由  回復  更多評論   

我現在討論的不是迭代,任何集合都能迭代,光用一個iterator去遍歷,任何集合都沒有差別了。那一個vector就夠了還要list和deque做什么?

我現在討論的是它們的內部結構的差別,根據不同的場景而要用出這些集合的差別才是真道理,樓上看清楚,我現在就是想在外部指針去引用集合內部的元素,就是不想每次訪問的時候都去迭代,集合如果只增不減的情況下,用deque是穩定的,而vector是不穩定的,vector存在空間重排,deque不存在空間重排,這是我要闡述的觀點
2009-05-24 14:01 | 李侃

# re: 今天找到一個不得不用deque的理由  回復  更多評論   

用deque是穩定的
2009-05-24 15:38 | 九久讀書人

# re: 今天找到一個不得不用deque的理由  回復  更多評論   

我試了試,似乎erase中間的元素以后,各元素的地址依然穩定,vc自帶的的deque 是這樣的,不知道其他版本的deque會不會也是這樣?

我已經深深的愛上deque了 ^^
2009-05-24 15:52 | 李侃

# re: 今天找到一個不得不用deque的理由  回復  更多評論   

std::deque<int> dq;
...
int& elem = dq[i];
dq.push_back(100);
elem = 99; // ok!

這樣的代碼對deque即使正確也還是不要用吧。
2009-05-24 16:55 | 阿淡

# re: 今天找到一個不得不用deque的理由  回復  更多評論   

后面的部分是我摘錄網上的文章,覺得好像也沒什么不妥
當然了如果元素被移除了,這樣去訪問那會是危險的。
2009-05-24 17:32 | 李侃

# re: 今天找到一個不得不用deque的理由  回復  更多評論   

個人意見是,不要直接引用容器內的元素地址,特別是長期引用
就算你知道自己在做什么,別人也不知道
2009-05-24 18:01 | LOGOS

# re: 今天找到一個不得不用deque的理由  回復  更多評論   

依賴于一個容器是否分配內存本身就是你的問題,不是該不該vector還是queue的問題。如果想避免分配內存帶來的問題,請用vector<shared_ptr<OBJ>>。
2009-05-24 21:25 | 陳梓瀚(vczh)

# re: 今天找到一個不得不用deque的理由  回復  更多評論   

我明白,如果是vector<Entity*>的方式,根本不用去討論該去用vector還是queue,重排就重排了,指針不會變
但如果是vector<Entity> 的形式情況就不同了

這樣的類別的集合確實就不該直接去引用集合中元素的地址,這不是一個好的習慣。

主要是:我的序列化存儲層只能支持 集合<entity>的形式
不支持 集合<Entity*>的形式,想引用從文件讀取的集合數據又不想做太多的拷貝,迫于無賴。

只好回頭再想想看有沒有更好的折中方案了。

2009-05-24 22:34 | 李侃

# re: 今天找到一個不得不用deque的理由  回復  更多評論   

不想拷貝又不想自己釋放,用智能指針。
2009-05-25 10:28 | 陳梓瀚(vczh)

# re: 今天找到一個不得不用deque的理由  回復  更多評論   

deque 不能 memcpy
2009-05-26 21:21 | lovelypig

# re: 今天找到一個不得不用deque的理由  回復  更多評論   

STL只是一份標準還不是實現,作為vector來講,它設計目標應該是作為一個大小伸縮的數組,比如&v[0]可以當作一個數組的指針(如果!v.empty()的話),而deque則不行;deque為了能夠以常數時間在順序容器的頭部及尾部進行push操作而設計的,但這個設計的代價通常很大,應該并不是你所想像的二維數組的形式,比如SGI的deque設計就采用了一種類似于文件系統中二級表的方式,其直接結果就是迭代器操作的代價很高。現實程序中你會發現很少有人會用deque,這固然有書中介紹比較少的原因,但也與其操作代價較高是分不開的。
我的意見是,除非不得以,否則使用vector而不要用deque;
你的這種情況,我建議你可以自己寫一個容器,那怕是用memove,通常也會比std::vector快很多的
2009-08-09 19:58 | 李現民

# re: 今天找到一個不得不用deque的理由  回復  更多評論   

deque用的不當,會造成內存急劇消耗!
2009-09-25 20:39 |

# re: 今天找到一個不得不用deque的理由  回復  更多評論   

本來就是各有所長的設計,vector設計規范就是連續,引用元素說得清清楚楚就是即時有效,不能緩存,你就要違背規范使用,還要說它不好,那是你愚蠢還是它不對呢?
各種容器就是為了滿足不同需求設計的,各有所長各取所需,但不要說一個取代另一個的蠢話,如果你覺得要取代了,說明你還認識不夠,也說明你起初選擇的時候是愚蠢的。
2012-05-10 13:07 | oldworm

# re: 今天找到一個不得不用deque的理由[未登錄]  回復  更多評論   

@李侃
STL用迭代器隱藏了線性容器間的區別,但這不代表因此各容器就沒區別吧?
每個容器都有自己的特點,不同應用場合性能是有差異的,所以才提供這么多線性表容器吧?
遍歷STL線性表還是用迭代器,C語法和C++語法混合起來用是不安全的。
2012-07-06 14:27 | Sine
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            91久久精品国产91性色tv| 亚洲精品综合精品自拍| 亚洲欧美日韩在线观看a三区| 亚洲国产色一区| 欧美aⅴ一区二区三区视频| 美国三级日本三级久久99| 牛牛影视久久网| 亚洲国产成人精品久久| 亚洲国产精品美女| 日韩一区二区精品| 午夜精品久久久久久久男人的天堂 | 久久精品1区| 玖玖综合伊人| 男人的天堂亚洲| 欧美日韩在线一区| 狠狠噜噜久久| 久久亚洲不卡| 亚洲韩国青草视频| 亚洲一区二区三区四区中文| 亚洲男人影院| 欧美xxx成人| 国产精品免费网站| 亚洲福利视频网| 亚洲欧美在线磁力| 亚洲国产成人av好男人在线观看| 中文国产成人精品久久一| 久久国产精品久久久久久久久久| 麻豆精品精品国产自在97香蕉| 欧美国产综合视频| 国语自产精品视频在线看一大j8| 亚洲国产天堂久久国产91| 午夜日韩视频| 日韩亚洲视频| 欧美顶级大胆免费视频| 国产精品色婷婷久久58| 亚洲激情欧美激情| 久久福利资源站| 91久久精品国产91久久性色tv| 欧美在线啊v一区| 国产精品大片免费观看| 亚洲青涩在线| 免费在线观看精品| 久久成人综合网| 亚洲免费成人av电影| 久久久亚洲精品一区二区三区| 欧美精品一线| 日韩一级精品视频在线观看| 久久久久久国产精品一区| 亚洲天堂成人在线观看| 欧美日韩免费高清一区色橹橹| 韩国精品主播一区二区在线观看| 亚洲综合第一| 99伊人成综合| 欧美精品一区二区三区久久久竹菊| 一区视频在线| 久久人体大胆视频| 久久gogo国模裸体人体| 国产亚洲美州欧州综合国| 亚洲欧美中文日韩v在线观看| 亚洲精品裸体| 欧美人妖另类| 亚洲网站在线看| 中文网丁香综合网| 欧美日韩中字| 亚洲欧美日韩国产精品| 一区二区三区 在线观看视频| 欧美精品一区二区视频| 日韩视频一区二区三区| 91久久夜色精品国产九色| 欧美经典一区二区三区| 妖精视频成人观看www| 亚洲激情第一页| 欧美国产在线电影| 亚洲一区欧美激情| 亚洲在线一区二区| 国产一区二区三区久久 | 亚洲国产精品电影在线观看| 久久深夜福利| 久久夜色精品| 日韩一级精品视频在线观看| 亚洲免费成人av| 国产欧美一级| 欧美丰满少妇xxxbbb| 蜜桃av综合| 中日韩在线视频| 亚洲欧美日韩国产一区二区| 在线播放国产一区中文字幕剧情欧美 | 你懂的视频欧美| 亚洲精品午夜精品| 亚洲精选中文字幕| 国产日韩一区二区| 亚洲国产精品国自产拍av秋霞| 亚洲国产精品尤物yw在线观看| 亚洲免费久久| 亚洲午夜高清视频| 精品88久久久久88久久久| 欧美国产精品v| 欧美日韩直播| 模特精品在线| 国产精品国产三级国产专区53 | 免费看的黄色欧美网站| 欧美激情综合五月色丁香| 亚洲一区二区在线播放| 久久伊人免费视频| 亚洲欧美日韩精品久久久久| 久久国产精品第一页| 夜夜精品视频| 久久国产精品亚洲va麻豆| 99国产精品久久久久久久久久| 亚洲欧美日韩精品久久久| 亚洲国产精品一区二区第一页 | 欧美激情中文字幕一区二区| 欧美日韩一区不卡| 免费视频亚洲| 国产精品男女猛烈高潮激情| 欧美激情精品久久久久久黑人| 国产日韩欧美电影在线观看| 亚洲精品国产视频| 在线成人av| 欧美中文字幕第一页| 亚洲综合视频一区| 欧美日韩精品一区| 亚洲高清av在线| 国内精品久久久久国产盗摄免费观看完整版 | 在线一区二区三区四区五区| 久久精品人人爽| 久久久一区二区三区| 国产日韩成人精品| 一区二区三区日韩精品| 一区二区三区欧美激情| 欧美大片一区| 亚洲国产乱码最新视频| 亚洲国产一区二区三区高清| 欧美在线观看视频在线| 久久久精品tv| 国产女同一区二区| 亚洲宅男天堂在线观看无病毒| 亚洲专区一区二区三区| 欧美日韩成人免费| 一本色道久久88综合亚洲精品ⅰ| 日韩一级精品| 欧美日韩国产精品一区| 99国产精品久久久久老师| 在线一区亚洲| 国产精品日韩在线播放| 亚洲免费视频观看| 久久精品国产亚洲精品| 国产在线高清精品| 欧美成va人片在线观看| 欧美激情1区2区3区| 亚洲国产欧美在线| 欧美日本高清视频| 亚洲图片在线观看| 欧美中文字幕在线视频| 狠狠色2019综合网| 久久久蜜桃精品| 亚洲高清免费| 亚洲一区二区三区中文字幕在线| 国产精品久久久久久模特| 亚洲欧美日韩国产综合在线| 久久免费精品日本久久中文字幕| 在线国产精品一区| 欧美日韩精品在线播放| 中文欧美字幕免费| 久久天天躁夜夜躁狠狠躁2022 | 亚洲午夜视频在线| 国产亚洲一区二区三区| 欧美激情四色| 亚洲永久免费av| 亚洲第一成人在线| 久久不射2019中文字幕| 亚洲三级视频| 国产一区日韩一区| 欧美日韩精品免费观看| 久久国产综合精品| 国产精品99久久久久久www| 久久综合99re88久久爱| 一区二区不卡在线视频 午夜欧美不卡' | 日韩亚洲一区在线播放| 久久国产综合精品| 一本一道久久综合狠狠老精东影业| 国产精品啊啊啊| 欧美二区在线播放| 欧美在线免费播放| 亚洲免费播放| 亚洲福利在线视频| 久久久久久一区二区| 亚洲一区二区在线看| 亚洲激情成人在线| 狠狠综合久久| 国产精品免费看| 欧美美女bb生活片| 久久久久久久尹人综合网亚洲| 一区二区三区四区五区视频| 欧美激情在线有限公司| 久久久久亚洲综合| 欧美一级黄色网| 亚洲一区观看| 亚洲人成人一区二区在线观看| 狠狠久久亚洲欧美专区|