Boost原始碼剖析之 容器賦值 assign

2021-04-19 22:35:54 字數 2997 閱讀 8445

相信大多數使用stl的人都是為了使用裡面的容器,使用vector、list、map的程式設計師對以下**可以說是非常熟悉了:

vector i_v;

i_v.push_back(1);

i_v.push_back(2);

i_v.push_back(3);

i_v.push_back(4);

i_v.push_back(5);

挺枯燥,是吧?用boost的assignment庫可以讓這一過程簡潔得多:

#include "boost/assign/std/vector.hpp"

using

namespace boost::assign;

vector i_v;

i_v += 1,2,3,4,5;

效果與上面的程式一致,可讀性卻好很多,看上去有點「指令碼語言」的感覺了。

對於關聯容器,也有類似的便潔方法:

#include "boost/assign/list_inserter.hpp"

#include "string"

using

namespace std;

using

namespace boost::assign;map months;

insert( months )

( "january", 31 )( "february", 28 )

( "march", 31 )( "april", 30 )

( "may", 31 )( "june", 30 )

( "july", 31 )( "august", 31 )

( "september", 30 )( "october", 31 )

( "november", 30 )( "december", 31 );

分析assign的源**,以vector為例,先看:

//assign/std/vector.hpp:

template

< class v, class a, class v2 >

inline list_inserter< assign_detail::call_push_back< std::vector >, v >

operator+=( std::vector & c, v2 v )

操作符+=已被過載,它的任務是返回乙個list_inserter類,這是assign中的核心類之一。再看push_back,它也沒有實質性的動作,只是建立乙個list_inserter然後返回它。

template

< class c >

inline list_inserter< assign_detail::call_push_back ,

boost_deduced_typename c::value_type >

push_back( c& c )

這裡的call_push_back(c)實際是建立乙個類call_push_back的例項,以使生成的list_inserter能夠知道自己該怎樣進行操作。

template

< class c >

class call_push_back

template

< class t > void

operator()( t r )

};

make_list_inserter和stl中的make_pair類似,都是用於包裝實現類的,真正的實現是利用list_inserter。

template

< class function, class argument >

inline list_insertermake_list_inserter( function fun, argument* )

list_inserter過載了+=操作符,所以才有 i_v+=1,2,3,4,5 這種寫法。可以看出 push_back函式返回乙個list_inserter,對應例子,i_v+=1變為push_back(i_v)(1),其中的push_back(i_v) (注意:不包括後面的「(1)」!) 變為make_list_inserter(call_push_back(i_v), 0),最後make_list_inserter返回的是list_inserter< call_push_back, int>例項,現在可以加上後面的「(1)」了,由於list_inserter過載了「()」操作符,所以此時值1才被list_inserter接收。

那數字間的逗號又是怎麼處理的呢?大家還記不記得 std::cout<< 1 << 2 << 3; 此處的《和assign中的逗號其實是乙個道理,《操作符返回乙個iostream,而逗號操作符返回乙個 list_inserter 。「+=」操作符返回第乙個list_inserter,其它的逗號「跟進」:

template

< class function, class argument = assign_detail::forward_n_arguments >

class list_inserter

....

list_inserter& operator()()

template

< class t >

list_inserter& operator,( const t& r )

private: function insert_;

}

這裡的insert_就是先前的assign_detail::call_push_back ( c ),所以insert_( r )就是 assign_detail::call_push_back ( c )( r )。

list_inserter還有repeat,repeat_fun,range等方法,分別對應assign中 i_v+=1,repeat(2,4),3....等寫法的實現。針對vector的assign基本就是這樣,至於map等其它容器的assign,實現與此類似。

STL原始碼剖析之序列式容器

最近由於找工作需要,準備深入學習一下stl原始碼,我看的是侯捷所著的 stl原始碼剖析 之所以看這本書主要是由於我過去曾經接觸過一些台灣人,我一直覺得台灣人非常不錯 這裡不涉及任何政治,僅限個人感受 在技術上他們比較嚴謹,在為人處世上也非常謙虛,所以一些台灣的技術資料我覺得是值得一看的。想要學習st...

STL原始碼剖析 容器 RB tree

rb tree,全稱是red black tree,又稱為 紅黑樹 紅黑樹本質上是一種二叉查詢樹,但它在二叉查詢樹的基礎上額外新增了乙個標記 顏色 同時具有一定的規則。這些規則使紅黑樹保證了一種平衡,插入 刪除 查詢的最壞時間複雜度都為o logn 每個節點不是紅色就是黑色 根結點永遠都是黑色 所有...

STL原始碼剖析 容器 vector

vector 常被稱為向量容器,因為該容器擅長在尾部插入或刪除元素,在常量時間內就可以完成,時間複雜度為o 1 而對於在容器頭部或者中部插入或刪除元素,則花費時間要長一些 移動元素需要耗費時間 時間複雜度為線性階o n vector實現的關鍵在於其對大小的控制以及重新配置時的資料移動效率。vecto...