生活随笔
收集整理的這篇文章主要介紹了
boost开发指南
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
C++確實很復雜,神一樣的0x不知道能否使C++變得純粹和干爽?
??? boost很復雜,感覺某些地方有過度設計和太過于就事論事的嫌疑,對實際開發工作的考慮太過于理想化。學習boost本身就是一個復雜度,有魄力在項目中廣泛采用boost復雜度會再加一層,抓狂的編譯時間,井噴式的編譯錯誤,運行時崩潰后的咒語式堆棧……
??? 其中好的東西還是值得用的,但凡事有個度。如果將應用做到boost這個級別了,要么你很牛,要么你在裝。
??? 用不用,看看還是有好處的。建議中高級以上C++程序員了解boost。
第1章 Boost程序庫總論
使用Boost,將大大增強C++的功能和表現力
?
第2章 時間與日期
timer提供毫秒級的計時精度,內部是通過std::clock取時間的progress_timer自動打印某生命周期的執行時間原則上程序庫的代碼是不應該被用戶修改的progress_display可以在控制臺上顯示程序的執行進度date_time庫能很好的表示日期時間概念,并能和C的時間結構tm進行友好互轉date類提供年月日和星期幾的概念。data可通過from_string或from_undelimited_string從字符串解析而來,可通過to_simple_string、to_iso_string、to_extended_iso_string轉換為字符串。(精度到天的DateTime)day_clock是精度到天的時鐘date_duration表示的是天精度的時間間隔概念,別名為days,另外還有years、months、weeksdate_period表示兩個date之間的日期區間(精度到天的TimeSpan)date_iterator、week_iterator、month_iterator和year_iterator是時間的迭代器boost::greorian::gregorian_calendar中有實用靜態方法:is_leap_year、end_of_month_daytime_duration表示微妙或納秒級的時間概念,幾個實用子類:hours、minutes、seconds、millisec/milliseconds、microsec/microseconds、nanosec/nannosecondsduration_from_string可以從字符串解析time_durationptime用來表示時間點,相當于date和time_duration的組合。可以用time_from_string或from_iso_string解析。(TimeSpan)
ptime now1 = second_clock::local_time(); // 得到本地當前秒精度時間
ptime now2 = microsec_clock::universal_time(); // 得到本地當前微秒精度時間time_period表示兩個ptime之間的時間區間。(DateTime)時間迭代器沒有日期迭代器那么多,只有time_iterator一個(boost時間日期庫亂、破碎、過度設計)
?
?第3章 內存管理
scoped_ptr類似auto_ptr,但其一旦獲得對象的管理權,你就無法再從它那里取回來。該智能指針只希望在本作用域里使用,不希望被轉讓。auto_ptr有意設計成所有權的自動轉讓,scoped_ptr有意設計成所有權的無法轉讓。scoped_ptr和auto_ptr均不能作為容器元素。scoped_array包裝的是new[]產生的指針,并調用的是delete[]。往往是用來和C代碼保持兼容,一般不推薦使用無論是編譯器還是程序員都很難區分出new[]和new分配的空間,錯誤的運用delete將導致資源異常在C++歷史上曾經出現過無數的引用計數型智能指針實現,但沒有一個比得上boost::shared_ptr,在過去、現在和將來,它都是最好的shared_ptr支持的轉型有:static_pointer_cast<T>、const_pointer_cast<T>、dynamic_pointer_cast<T>,返回的結果是shared_ptr,并能保證這些指針的引用計數正確用shared_ptr可以消除代碼中顯示的delete,用make_shared、allocate_shared可以消除代碼中顯示的new橋接模式(bridge)是一種結構型設計模式,它把類的具體實現細節對用戶隱藏起來,以達到類之間的最小耦合關系。在具體編程實踐中橋接模式也被稱為pimpl或者handle/body慣用法,它可以將頭文件的依賴關系降到最小,減少編譯時間,而且可以不使用虛函數實現多態get_deleter(shared_ptr<T> const& p)可以獲得刪除器。shared_ptr的刪除器在處理某些特殊資源時非常有用,它使得用戶可以定制、擴展shared_ptr的行為,使其不僅僅能夠管理內存資源,而是稱為一個“萬能”的資源管理工具對應shared_ptr,也有一個shared_array,scoped_array和shared_array均不對operator[]做下標檢測weak_ptr是為配合shared_ptr而引入的,更像是shared_ptr的一個助手而不是智能指針,其沒有重載operator*和->,不具有普通指針的行為。它最大的作用在于協助shared_ptr工作,像旁觀者那樣觀測資源的使用情況weak_ptr被設計為與shared_ptr共同工作,可以從一個shared_ptr或者另一個weak_ptr對象構造,獲得資源的觀測權。但weak_ptr沒有共享資源,它的構造不會引起指針引用計數的增加。同樣,在weak_ptr析構時也不會導致引用計數的減少,它只是一個靜靜的觀察者獲得this指針的shared_ptr,使對象自己能夠產生shared_ptr管理自己:class T : public enable_shared_from_this<T>, then shared_ptr shared_from_this().intrusive_ptr是一個侵入式的引用計數型指針。當對內存占用的要求非常嚴格,或現存代碼已經有了引用計數機制時可以考慮。一般情況不推薦使用。pool為固定塊大小的類似malloc的原生內存分配器,支持數組式分配,一般情況下不必對分配的內存調用free()。只分配原生內存,不調用構造函數,回收不調用析構函數,最好不要用于對象。singleton_pool和pool接口完全一致,但為單件線程安全,同樣要求編譯期指定要分配的原生內存塊大小object_pool為特定類型的對象池,不支持數組式分配,支持對象分配和對象原生內存分配pool_alloc和fast_pool_allocator是boost提供的兩個STL分配器。除非有特別需求,我們應該總使用STL實現自帶的內存分配器。使用定制的分配器需要經過仔細的測試,以保證它與容器可以共同工作。內存管理是C++程序開發中永恒的話題,因為沒有GC,小心謹慎的管理內存等系統資源是每一個C++程序員都必須面對的問題
?
第4章 實用工具
private繼承自noncopyable可以編譯時禁止對象拷貝語法C++靜態強類型的優點有時候反而是阻礙程序員生產力的“缺陷”typeof庫使用宏模擬了C++0X中的typedef和auto關鍵字,可以減輕書寫繁瑣的變量類型聲明工作,簡化代碼。對于用戶自定義類型需要手工用宏注冊。(語法并沒那么好看,不準備使用)optional<T>使用“容器”語義,包裝了“可能產生無效值”的對象,實現了“未初始化”的概念(Nullable<T>)optional<T> make_optional(bool condition, T const& v)用來簡單構建optional對象,但不能處理optional<T&>的情況。(此乃雞肋)?optional<string> str(in_place("string就地創建")),而不需拷貝臨時對象,避免大對象的拷貝開銷用于初始化的assign庫(僅限于STL標準容器,通過重載“+=”和“,”運算符實現):
#include <boost/assign.hpp>
using namespace boost;
vector<int> v; v += 1,2,3,4,5,6*6;
set<string> s; s += "cpp", "java";
map<int, string> m; m += make_pair(1, "one"), make_pair(2, "2");assign還支持insert()、push_front()、push_back()(通過重載“()”實現):
vector<int> v; push_back(v)(1)(2)(3)(4)(5);
list<string> l; push_front(l)("cpp")("java");
set<double> s; insert(s)(3.14)(0.618)(1.732);
map<int, string> m; insert(m)(1, "one")(2, "two");assign也可以將“()”和“,”混用:
vector<int> v;
push_back(v), 1, 2, 3, 4, 5;
push_back(v)(6), 7, 64 / 8, (9), 10;
deque<string> d;
push_front(d)() = "cpp", "java";assign list_of()函數:
vector<int> v = list_of(1)(2)(3);
deque<string> d = (list_of("cpp")("java"));
set<int> s = (list_of(10), 20, 30, 40);
map<int, string> m = list_of(make_pair(1, "one")) (make_pair(2, "two"))
如果需要將括號與逗號混合使用,則要求最外側加一個括號,否則編譯器無法推導assign map_list_of/pair_list_of函數:
map<int, int> m1 = map_list_of(1, 2)(3, 4)(5, 6)
map<int, string> m2 = map_list_of(1, "one")(2, "two")assign tuple_list_of用戶初始化元素類型為tuple的容器assign repeat()可以重復生成值,repeat_fun()可以重復無參函數或仿函數,range()則可以從序列中取出部分或全部:
vector<int> v = list_of(1).repeat(3, 2)(3)(4)(5); // v = 1,2,2,2,3,4,5
multiset<int> ms; insert(ms).repeat_fun(5, &ran).repeat(2, 1), 10; // ms = x,x,x,x,x,1,1,10
deque<int> d; push_front(d).range(v.begin(), v.begin() + 5); // d=3,2,2,2,1assign支持8個STL標準容器(vector、string、deque、list、set、multiset、map、multimap),對容器適配器(stack、queue、priority_queue)則需要通過to_adapter():
stack<int> stk = (list_of(1), 2, 3).to_adapter();
queue<string> q = (list_of("cpp")("java")).repeat(2, "C#").to_adapter();
priority_queue<double> pq = (list_of(1.414), 1.732).to_adapter();assign也支持部分不在STL中的非標準容器slist、hash_map、hash_set,因為其符合標準容器定義,同時也支持大部分boost容器:array、circular_buffer、unordered等assign list_of()嵌套:
vector<vector<int>> v = list_of(list_of(1)(2)) list_of(list_of(3)(4));
v += list_of(5)(6), list_of(7)(8);assign ref_list_of()、cref_list_of()、ptr_push_back()、ptr_list_of()還支持以引用或指針來構造初始化:
int a = 1, b = 2, c = 3;
vector<int> v = ref_list_of<3>(a)(b)(c);boost::swap是對std::swap的增強,并且擴充了對數組的支持:
int a1[10]; std::fill_n(a1, 10, 5);
int a2[10]; std::file_n(a2, 10, 20);
boost::swap(a1, a2);單件boost::details::pool::singleton_default<T>在main之前進行構造,支持繼承或非繼承形式(最恨main之前的事情了)單件boost::serialization::singleton<T>在main之前進行構造,支持繼承或非繼承形式。繼承方式更徹底一些,非繼承方式不影響原有代碼boost::tribool三態bool,indeterminate(tribool)可判斷一個三態bool是否處于不確定狀態選擇optional<bool>還是tribool:如果返回值可能是無效的,那么就是optional<bool>,如果返回值總是確定的,但可能無法確定其意義,那么就用tribool(最多自己隨手定義個enum狀態,為了這點需求需要記住這一堆名稱和細節!)using namespace std::rel_ops; 則一旦為類定義了operator==和<,則自動具有!=、>、<=和>=的功能。boost operators庫提供了對該功能的增強,使用時只需繼承自這些類并提供指定的operator重載即可獲得附送的重載: equality_comparable<T>:要求提供==,可自動實現!=,相等語義less_than_comparable<T>:要求提供<,可自動實現>、<=、>=addable<T>:要求提供+=,可自動實現+subtractable<T>:要求提供-=,可自動實現-incrementable<T>:要求提供前置++,可自動實現后置++decrementable<T>:要求提供前置--,可自動實現后置--equivalent<T>:要求提供<,可自動實現==,等價語義totally_ordered:全序概念,組合了equality_comparable和less_than_comparableadditive:可加減概念,組合了addable和subtractablemultiplicative:可乘除概念,組合了multipliable和diviablearithmetic:算術運算概念,組合了additive和multiplicativeunit_stoppable:可步進概念,組合了incrementable和decrementablepublic dereferenceable<T, P, (B)>:解引用操作符,要求提供operator*,可自動實現operator->。P為operator->返回類型,一般為T*public indexable<T, I, R, (B)>:下標操作符,I為下標類型,要求能夠與類型T做加法操作,通常為int;R是operator[]的返回值類型,通常是一個類型的引用。要求提供operator+(T, I),將自動實現operator[] 如果只關心類的等價語義,那么就用equivalent,如果想要精確的比較兩個對象的值,就是用equality_comprable。相等equivalent基于"=="實現,而equality_comprable基于"<"的"!(x<y)&&!(x>y)"實現。應該總對異常類是用虛繼承struct my_exception :
? virtual std::exception,? // 兼容C++標準異常
? virtual boost::exception
{};
typedef boost::error_info<struct tag_err_no, int> err_no;
typedef boost::error_info<struct tag_err_str, string> err_str;
#include <boost/exception/all.hpp>
try { throw my_exception() << err_no(10); }
catch(my_exception& e)
{
??? cout << *get_error_info<err_no>(e) << endl;
??? cout << e.what() << endl;
??? e << err_str("向異常追加信息,還可再次拋出");
??? cout << *get_error_info<err_str>(e) << endl;
}從exception派生的異常定義非常簡單,沒有實現代碼,可以很容易建立起一個適合自己程序的、驚喜完整的異常類體系。只要都是用虛繼承,類體系可以任意復雜。boost庫預定義的異常類型:
typedef error_info<struct errinfo_api_function_, char const*> errinfo_api_function;
typedef error_info<struct errinfo_at_line_, int> errinfo_at_line;
typedef error_info<struct errinfo_file_handle_, weak_ptr<FILE>> errinfo_file_handle;
typedef error_info<struct errinfo_file_name_, std::string> errinfo_file_name;
typedef error_info<struct errinfo_file_open_mode_, std::string> errinfo_file_open_mode;
typedef error_info<struct errinfo_type_info_name_, std::string> error_info_type_info_name;
typedef error_info<struct throw_function_, char const*> throw_function;
typedef error_info<struct throw_file_, char const*> throw_file;
typedef error_info<struct throw_line_, ine> throw_line;enable_error_info<T>(T& e),可以將已將存在的任意類型包裝為boost異常類型throw_exception(任意異常類型),可以自動將任意異常類型包裝為boost異常,還能保證線程安全diagnostic_information(e)可以得到任意boost異常的字符串內容描述;在catch塊中調用current_exception_diagnostic_information(),則不用傳參數e。(何必呢,為少寫一兩個字母反而要記住一個更長的名字)catch塊內的異常轉型用current_exception_cast<T>()catch塊內調current_exception()得到當前異常指針的exception_ptr是線程安全的,rethrow_exception可以重新拋出異常UUID, Universally Unique Identifier, 128bit(16 Byte),不需要中央認證機構就可以創建全球唯一的標識符。別名GUID不是所有的警告都可以忽略的,有的警告預示著可能潛在的錯誤BOOST_BINARY(111 00 1),可以實現編譯器的二進制定義,但不能超過8bit
第5章 字符串與文本處理
lexical_cast<T>(X),可以實現字符串和數值類型之間的轉換,但不支持高級格式控制。轉換失敗將拋出bad_lexical_cast異常。lexical_cast底層用C++流實現,要求目標類型支持operator<<、operator>>、無參構造函數和拷貝構造函數cout << format("%s:%d+%d=%d\n") %"sum" %1 %2 %(1+2); // sum:1+2=3
format fmt("(%1%?+?%2%) *?%2%?=?%3%\n");
fmt %2 %5;
fmt %((2+5)*5);
cout << fmt.str(); // (2 + 5) * 5 = 35format在提供的參數過多或過少的情況下operator<<或str()都會拋出異常format完全支持printf的格式化選項方式,同時還增加了新的方式: %|spec|%:與printf格式選項功能相同,但兩邊增加了豎線分隔,可以更好的區分格式化選項有普通字符%N%:標記第N個參數,相當于占位符,不帶任何其他的格式化選項 format因為做了很多安全檢查工作,會比printf慢至少2-5倍format相關的高級功能: basic_format&?bind_arg(int argN, const T& val) 把格式化字符串第argN位置的輸入參數固定為val,即使調用clear()也保持不變,除非調用clear_bind()或clear_binds()basic_format&?clear_bind(int argN) 取消格式化字符串第argN位置的參數綁定basic_format&?clear_binds()basic_format& modify_item(int itemN, T manipulator) 設置格式化字符串第itemN位置的格式化選項,manipulator是一個boost::io::group()返回的對象boost::io::group(T1 a1, ..., Var const& var) 是一個最多支持10個參數的模板函數,可以設置IO流操縱器以指定格式或輸入參數值 string_algo庫包括: to_upper, to_lower, starts_with, ends_with, contains, equals, lexicographical_compareall(檢測字符串中的所有元素是否滿足給定的判斷式)仿函數is_equal, is_less, is_not_greateris_space, is_alnum, is_alpha, is_cntrl, is_digit(十進制數字), is_graph, is_lower, is_print, is_punct(是否是標點符號), is_upper, is_xdigit(字符是否為十六進制數字), is_any_of(字符是否是參數字符序列中的任意數字), if_from_range(字符是否位于指定的區間[c1,c2]內)trim_left、trim_right、trimfind_first、find_last、find_nth、find_head、find_tailreplace/erase_first、replace/erase_last、replace/erase_nth、replace/erase_all、replace/erase_head、replace/erase_tailfind_all、split、find_iterator、split_iterator、join tokenizer類似string_algo::split,為更專業的token劃分工具。tokenizer庫提供預定義好的四個分詞對象: char_delimiter_separator:使用標點符號分詞,是默認的分詞函數對象。已被聲明廢棄char_separator:支持一個字符集合作為分隔符,默認行為與char_delimiter_separator類似escaped_list_separator:用于CSV格式的分詞offset_separator:使用偏移量來分詞 xpressive,類似boost.regex的正則表達式解析器,同時還是一個類似于boost.spirit的語法分析器,并且將這兩種完全不相交的文本處理方式完美的融合在了一起xpressive使用regex_token_iterator<>提供了強大的分詞迭代器
第6章 正確性測試
測試對于軟件開發是非常重要的,程序員——尤其是C++程序員更應該認識到這一點BOOST_ASSERT宏類似于assert宏,提供運行時斷言,但功能有所增強。可以通過BOOST_DISABLE_ASSERTS來關閉。當定義BOOST_ENABLE_ASSERT_HANDLER后,斷言觸發時將會調用boost::assertion_failed回調BOOST_VERIFY類似BOOST_ASSERT,但斷言表達式一定會被求值,Release下仍然會失效(放棄BOOST_VERIFY)BOOST_STATIC_ASSERT,編譯時斷言。可以出現在程序的任何位置,而不一定只在函數域內測試用例是一個包含多個測試斷言的函數,它是可以被獨立執行測試的最小單元,各個測試用例之間是無關的,發生的錯誤不會影響到其他測試用例
?
第7章 容器與數據結構
array是的C原生數組的STL接口包裝std::vector<bool>是vector對bool的特化,內部保存的實際為bit,支持動態長度。std::bitset大小固定,但支持更多的位運算boost.dynamic_bitset類似std::vector<bool>可以動態長度,同時提供了豐富的位運算。dynamic_bitset還支持集合相關操作哈希容器:boost::unordered_map、boost::unordered_set、boost::unordered_multimap、boost::unordered_multisetboost::bimap,雙向映射容器,提供left、right兩個試圖。支持的集合類型有:set_of、multiset_of、unordered_set_of、unordered_multiset_of、list_of、vector_of、unconstrained_set_ofbimap的左右視圖還可以通過標簽訪問:
bimap<tagged<int, struct id>, tagged<string, struct name>> bm;
bm.by<id>().insert(make_pair(1, "C++")); // 相當于使用左視圖
bm.by<name>().insert(make_pair("java", 2)); // 相當于使用右視圖circular_buffer<T>為大小固定的循環緩沖區,circular_buffer_space_optimized<T>類似circular_buffer<T>但只在確實需要時才分配內存,并且當容器內元素減少時自動釋放內存tuple是固定數目非同質元素容器。tuple是std::pair的泛化,可以從函數返回任意數量的值,也可以代替struct組合數據和std::make_pair對應,也有個make_tuple用來簡化tuple的創建tie()可以生成一個元素類型全是引用的tuple,相當于make_tuple(ref(a), ref(b), ...),可以用于左值,通常用來接收返回tuple或pair函數的返回值,可以看成是對tuple的解包element<N, T>::type可以給出T中第N個元素的類型,length<T>::value可以給出T的元素數量any能夠容納任意類型,可以用any_cast<T>(a)類型安全的取出any中的值(讓人聯想到Ogre::Any)any可以持有原始指針,但這樣的用法很不安全,會導致內存泄露。應該使用智能指針包裝原始指針,這樣在any析構時智能指針會自動的調用delete,從而安全的釋放資源如果希望一種數據結構具有tuple那樣的容納任意類型的能力,又可以在運行時動態變化大小,那么就可以用any作為元素類型搭配容器variant是對C/C++中union概念的增強和擴展。varinat是有界類型,元素類型范圍由用戶指定,any是無界類型,可以容納任意類型multi_array<int, 3>,相當于int ma[X][Y][Z]的多維數組。multi_array沒有異常機制來處理錯誤,保證數組范圍不越界是庫用戶自己的責任property_tree是一個保存了多個屬性值的樹形數據結構,可以用類似路徑的簡單方式訪問任意節點的樹形,而且每個節點都可以用類似STL的風格遍歷子節點。property_tree特別適合于應用程序的配置數據處理,可以解析xml、ini、json和info四種格式的文本數據,使用它能減輕自己開發配置管理的工作。
?
第8章 算法
boost foreach庫提供BOOST_FOREACH和BOOST_REVERSE_FOREACH來實現對容器的正向和反向遍歷minmax(a, b)可在一次處理中同時獲得最大最小值,執行效率上有很大提高(有提前優化的感覺了)minmax_element算法族可以得到迭代器區間內的最大最小值
?
第9章 數學與數字
從純數學的角度看,程序也不過是一個非常大的整數而已integer_traits : public std::numeric_limits,提供各種整數類型的編譯期最大最小值<boost/cstdint.hpp>基于C99標準中的<stdint.h>,定義了各種標準的整數<boost/integer.hpp>與<boost/cstdint.hpp>功能類似,用模板類而不是typedef提供各種整數類型定義boost.rational表示有理數(分數),rational_cast<R>可以將有理數轉換為普通數字最大公約數gcd();最小公倍數lcm()crc_optimal以字節為單位的快速CRC計算,實際常用的是crc_32_type的預定義算法boost random庫提供了26個偽隨機數發生器random庫提供的隨機數分布器: uniform_smallint:在小整數域內的均勻分布uniform_int:在整數域上的均勻分布uniform_01:在區間[0,1]上的實數連續均勻分布uniform_real:在區間[min,max]上的實數連續均勻分布bernoulli_distribution:伯努利分布binomial_distribution:二項分布cauchy_distribution:柯西(洛倫茲)分布gamma_distribution:伽馬分布poisson_distribution:泊松分布geometric_distribution:幾何分布triangle_distribution:三角分布exponential_distribution:指數分布normal_distribution:正態分布lognormal_distribution:對數正態分布uniform_on_sphere:球面均勻分布 variate_generator<Engine, Distribution>變量發生器,用于組合隨機數發生器和分布器真隨機數無法用純軟件產生,因為計算機本身是個確定的有限狀態自動機
?
第10章 操作系統相關
io_state_savers庫可以簡化恢復流狀態的工作,它能夠保存流的當前狀態,自動恢復流的狀態或者由程序員控制恢復的時機 基本的標準屬性保存器:ios_flags_saver、ios_width_saver增強的標準屬性保存器:ios_iostate_saver、ios_rdbuf_saver自定義的屬性保存器:ios_iword_saver、ios_pword_saver組合的屬性保存器:ios_all_saver system庫使用輕量級的對象封裝了操作系統底層的錯誤代碼和錯誤信息,使調用操作系統功能的程序可以被很容易的移植到其他操作系統
filesystem庫中的path和wpath提供了文件路徑相關的很多實用操作(類似Path)portable_posix_name()和windows_name()分別檢測文教案名字符串是否符合POSIX和Windows規范。Windows的文件名可以字符范圍比POSIX的大。native()判斷文件名是否符合本地文件系統命名規則為了程序的健壯性,應總使用try-catch來保護文件訪問代碼directory_iterator和wdirectory_iterator提供了迭代一個目錄下所有文件的功能recursive_directory_iterator和wrecursive_directory_iterator提供遞歸遍歷目錄功能program_options庫提供了強大的命令行參數處理功能,它不僅能夠分析命令行,也能夠從配置文件甚至環境變量中獲取參數,實現了非常完善的程序配置選項處理功能#include <boost/program_options.hpp>
using namespace boost::program_options;
int main(int argc, char* argv[])
{
? options_description opts("demo options");
? opts.add_options()
??? ("help", "just a help info")
??? ("filename", value<string>(), "to find a file");
? variables_map vm;
??store(parse_command_line(argc, argv, opts), vm);
? // 解析完成,實現選項處理邏輯
? if(vm.count("help"))
? {
??? cout << opts << endl;
??? return 0;
? }
? if(vm.count("filename"))
? {?cout << "find" << vm["filename"].as<string>() << endl; }
? if(vm.size() == 0)
? {?cout << "no options" << endl;?}
}program_options庫的解析程序選項功能由三個基本組件構成,分別是選項描述器、分析器和存儲器。選項描述其定義選項及選項的值,分析器依據選項描述器的定義解析命令行或數據文件,存儲器則把分析器的結果保存起來以供使用
第11章 函數與回調
result_of<Func(T1, T2)>::type確定一個調用表達式的返回類型,是實現泛型庫的底層基本構件ref()和cref()可以包裝對象的引用,在傳遞參數時消除對象拷貝的代價,或者將不可拷貝的對象變為可以拷貝bind是對標準庫bind1st、bind2nd的泛化和增強,可以適配任意的可調用對象。bind第一個參數必須是一個可調用對象,包括函數、函數指針、函數對象和成員函數指針bind也可以綁定到public成員變量,用法與綁定成員函數類似,只需要把成員變量名像一個成員函數一樣去使用bind綁定到仿函數時,要求仿函數typedef xxx result_type;否則就只能用bind<xxx>(functor())的形式bind重載了比較操作符和邏輯非操作符,可以把多個bind綁定式組合起來,形成一個復雜的邏輯表達式,配合標準庫算法可以實現語法簡單但語義復雜的操作:
using namespace boost::assign;
typedef rational<int> ri; // 有理數類
vector<ri> v?= list_of((ri(1, 2)) (ri(3, 4)) (ri(5, 6))); // 初始化
// 刪除所有分子為1的有理數
remove_if(v.begin(), b.end(), bind(&ri::numerator, _1) == 1);
assert(v[0].numerator() == 3); // 有理數1/2被刪除
// 使用find_if算法查找分子是1的有理數,不不存在
assert(find_if(v.begin(), b.end(), bind(&ri::numerator, _1) == 1) == v.end());
// 查找分子大于3且分母小于8的有理數
BOOST_AUTO(pos, find_if(v.begin(), b.end(), bind(&ri::numerator, _1) > 3 && bind(&ri::denominator, _1) < 8));
cout << *pos << endl; // 輸出5/6變長參數函數、__stdcall、__fastcall、extern "C"等函數bind時需要顯式指定返回值類型才行function是一個函數對象的“容器”,概念上像是C/C++中的函數指針類型的泛化,是一種“智能函數指針”調用空的function將拋出bad_function_call異常,最好在使用前通過empty()來測試有效性與原始的函數指針相比,function對象的體積要稍微大一點(3個指針的大小),速度要稍微慢一點(10%左右的性能差距),但這與它帶給程序的巨大好處相比是無足輕重的signals2基于boost中的另一個庫signals,實現了線程安全的觀察者模式。在signals2庫中,觀察者模式被稱為信號/插槽(sinals and slots),它是一種函數回調機制,一個信號關聯了多個插槽,當信號發出時,所有關聯它的插槽都會被調用signal是不可拷貝的,如果把signal作為自定義類的成員變量,那么自定義類也將是不可拷貝的,除非用shared_ptr來包裝signal.connection()連接插槽時,會返回一個connection對象,可以用來管理信號和插槽之間的連接關系signal2庫使用slot類提供了自動連接管理的功能,能夠自動跟蹤插槽的生命周期,但插槽失效時會自動斷開連接較之signals,signals2具有線程安全,能夠用于多線程環境,而且不需要編譯就可以使用
?
第12章 并發編程
thread庫提供的互斥量: mutex:獨占式互斥量timed_mutex:提供超時鎖定功能的獨占式互斥量recursive_mutex:遞歸式互斥量,可以多次鎖定,相應的也要多次解鎖recursive_timed_mutex:提供超時鎖定功能的遞歸式互斥量shared_mutex:multiple-reader/single-writer型的共享互斥量(讀寫鎖) scoped_lock和scoped_try_lock可以在退出作用域時確保unlock的調用<boost/detail/atomic_count.hpp>提供了一個原子計數器——atomic_count,使用long進行線程安全的遞增遞減計數信號量:condition_variable_any和condition_variablethread_group提供一個簡單的線程池,可以對一組線程統一操作thread庫使用future范式提供異步操作線程返回值的方法,因為這個返回值在線程開始執行時開始不可用的,是一個“未來”的“期望值”,所以被稱為future(期貨)。future使用packaged_task和promise兩個模板類來包裝異步調用,用unique_future和shared_future來獲取異步調用的結果
int fab(int n) // 遞歸計算斐波那契數列
{
??? if(n == 0 || n == 1) return 1;
??? return fab(n - 1) + fab(n - 2);
}
int main()
{
??? packaged_task<int> pt(bind(fab, 10)); // 聲明packaged_task對象,用模板參數指明返回值的類型,packaged_task只接受無參函數,因此需要使用bind
??? unique_future<int> uf = pt.get_future(); // 聲明unique_future對象,接受packaged_task的future值,同樣要用模板參數指明返回值類型
??? thread(boost::move(pt)); // 啟動線程計算,必須使用boost::move()來轉移packaged_task對象,因為packaged_task是不可拷貝的
??? uf.wait(); // unique_future等待計算結果
??? assert(uf.is_ready() && uf.has_value());
??? cout << uf.get() << endl; // 輸出計算結果89
}為了支持多個future對象的使用,future還提供wait_for_any()和wait_for_all()兩個自由函數,他們可以阻塞等待多個future對象,知道任意一個或者所有future對象都可用(is_ready())packaged_task通過包裝函數獲得異步調用返回值,而promise通過包裝函數輸出參數獲得返回值。在線程中用set_value()設置promise返回值,用get_future()獲得值
void fab2(int n, promise<int>* p) {?p->set_value(fab(n)); }
int main()
{
??? promise<int> p; // promise變量
??? unique_future<int> uf = p.get_future(); // 賦值future對象
??? thread(fab2, 10, &p); // 啟動計算線程
??? uf.wait(); // 等待future計算結果
??? cout << uf.get() << endl;
}thread庫提供了兩個自由函數lock()和try_lock(),可以一次鎖定多個互斥量,并且不會出現死鎖
lock(mu1, mu2);
...;
mu1.unlock(); // 逐個解鎖
mu2.unlock();多線程僅執行一次初始化需要使用一個once_flag對象,并把它初始化為BOOST_ONCE_INIT,然后使用call_once()來調用初始化函數,完成僅執行一次的初始化
once_flag of = BOOST_ONCE_INIT; // 一次初始化標志
void call_func() {?call_once(of, init_count); } // 執行一次初始化
int main()
{
??? (thread(call_func)); // 必須用括號括住臨時對象,否則編譯器會認為這是個空thread對象聲明
??? (thread(call_func));
??? this_thead::sleep(posix_time::seconds(1)); // 等待1秒鐘
}barrier(護欄)可用于多個線程同步,當線程執行到barrier時必須等待,直到所有的線程都達到這個點時才能繼續執行。thread_specific_ptr實現可移植的線程本地存儲機制(thread local storage, TLS)或線程專有存儲(thread specific storage, TSS),可以簡化多線程應用,提高性能
void printing()
{
??? thread_specific_ptr<int> pi; // 線程本地存儲一個整數
??? pi.reset(new int()); // 直接用reset()函數賦值
??? ++(*pi); // 遞增
??? mutex::scoped_lock lock(io_mu); // 鎖定io流操作
??? cout << "thread v=" << *pi << endl;
}this_thread名字空間下提供了at_thread_exit(func),允許注冊一個線程結束回調,無論線程是否被中斷。但線程意外終止的情況下,該回調不會被執行promise和packaged_task都支持回調函數,可以讓future延后在需要的時候獲得值,而不必主動啟動線程計算asio庫基于OS提供的異步機制,采用前攝器設計模式(Proactor)實現了可移植的異步或同步IO操作,而且并不要求使用多線程和鎖。目前asio主要關注與網絡通信方面,支持TCP、ICMP、UDP等網絡通信協議,還支持串口讀寫、定時器、SSL等功能。asio是一個很好的富有彈性的框架,可以擴展到其他有異步操作需要的領域。asio庫基于前攝器模式(Proactor)封裝了OS的select、poll/epoll、kqueue、overlapped I/O等機制,實現了異步IO模型。它的核心類是io_service,相當于前攝器模式中的Proactor角色,asio的任何操作都需要有io_service的參數與。 在同步模式下,程序發起一個IO操作,向io_service提交請求,io_service把操作轉交給OS,同步的等待。當IO操作完成時,OS通知io_service,然后io_service再把結果發回給程序,完成整個同步流程。異步模式下,程序出了要發起IO操作,還要定義一個用于回調的完成處理函數。io_service同樣把IO操作轉交給操作系統執行,但它不同步等待,而是立即返回。調用io_service的run()成員函數可以等待異步操作完成,當異步操作完成時io_service從OS獲取操作結果,調用完成處理函數asio不直接使用OS提供的線程,而是定義了strand以保證在多線程環境中無需使用互斥量。io_service::strand::wrap()可以包裝一個函數在strand中執行asio提供了mutable_buffer和const_buffer兩種可安全用于異步讀寫的緩沖區 ip::address表示IP地址,可以同時支持ipv4和ipv6兩種地址ip::tcp::endpoint表示ip地址和端口號同步socket示例: Server:
int main()
{
? try
? {
??? cout << "server start" << endl;
??? io_service ios; // asio程序必需的io_service對象
??? ip::tcp::acceptor acceptor(ios, ip::tcp::endpoint(ip::tcp::v4(), 6688);
??? cout << acceptor.local_endpoint().address() << end;
??? while(true)
??? {
????? ip::tcp::socket sock(ios);
????? acceptor.accept(sock); // 阻塞等待socket連接
????? cout?<< "client:" << sock.remote_endpoint().address() << endl;
????? sock.write_some(buffer("hello asio")); // 發送數據。不能直接把數組、vector等容器用做asio的讀寫參數,必須通過buffer()函數包裝
??? }
? }
? catch(std::exception& e) {?cout << e.what() << endl;?}
}Client:
void client(io_service& ios)
{
? try
? {
??? cout << "client start" << endl;
????ip::tcp::socket sock(ios); // 創建socket對象
????ip::tcp::endpoint ep(ip::address::from_string("127.0.0.1"), 6688); // 創建連接端點
????sock.connect(ep);
????vector<char> str(100, 0);
????sock.read_some(buffer(str)); // 使用buffer包裝緩沖區接收數據
????cout << "receive from " << sock.remote_endpoint().address() <<?&str[0] << endl;
? }
? catch(std::exception& e) {?cout << e.what() << endl;?}
}
int main()
{
? io_service ios;
? a_timer at(ios, 5, bind(client, ref(ios))); // 啟動定時器
? ios.run();
} 通常客戶端不需要異步通信resolver可實現域名解析interprocess可以處理進程間通信(IPC)
?
第13章 編程語言支持
任何程序開發語言都不可能獨當一面、包打天下,總有它的長處與短處python庫能夠在C++中調用Python語言,但它更重要的功能在于用C++編寫Python擴展模塊,嵌入到Python解釋器中調用,提高Python的執行效率C++中的構造函數不同于普通的成員函數,不能取其地址
?
第14章 其他Boost組件
regex:需要編譯才能使用的正則庫sprit:面向對象的遞歸下降解析器生成框架,使用EBNF語法gil:有Adobe贊助開發的通用圖像庫。為像素、色彩、通道等圖像處理概念提供了泛型的、STL式的容器和算法,可以對圖像做灰度化、梯度、均值、選裝等運算。支持jpg、png、tiff等格式graph:處理離散數學中的圖結構,并提供圖、矩陣等數據結構上的泛型算法。可以看做是STL在非線性容器領域的擴展。intrusive:侵入式容器。STL為非侵入式容器,不需要對容器內的元素類型做修改即可容納pointer container:提供了與STL類似的若干種指針容器,性能較好且異常安全。用STL+shared_ptr也可以做變通。multi_index:實現具有多個STL兼容訪問接口(索引)的容器iterators:定義一組基于STL的新迭代器概念、構造框架和游泳的適配器,能夠用來更輕松的實現迭代器模式range:基于STL迭代器提出的“范圍”概念,是一個容器的半開區間,使用range可以讓代碼更加簡單漂亮lambda:引入lambda表達式和函數式編程,可以就地創建小型的函數對象,避免函數定義離調用點太遠,更方便代碼維護。lambda表達式是一種新的編程范式,但其語法十分復雜,如果使用的不好很容易寫出過于晦澀難懂的代碼,使程序難以維護。signals:觀察者模式。功能和用法與signals2基本相同,非線程安全,需要編譯。如果沒有什么特殊理由,應該使用signals2庫enable_if:允許模板函數或者模板類在偏特化時僅針對某些特定類型有效,依賴于SFINAE(substitution failure is not an error)原則call_traits:封裝了可能是最好的傳遞參數給函數的方式,它會自動推導出最高效的傳遞參數傳遞類型type_traits:提供一組trait類,用以在編譯器確定類型是否具有某些特征。使用type_traits可以編寫出更好更高效的泛型代碼concept check:編譯器檢查模板函數或模板類的模板參數是否符合某個概念,是否運行進行模板參數推演。主要用來編寫泛型算法或實現泛型庫function_types:提供對函數、函數指針、函數引用和成員指針等類型進行分類、分解和合并的功能in_place_factory:直接構造對象而不需要一個臨時對象的拷貝proto:允許在C++中構建專用領域嵌入式語言,基于表達式模板技術定義小型專用語言的“編譯器”property map:提供key-value映射的屬性概念定義fusion:提供基于tuple的容器和算法,是模板元編程的強大工具,可以與mpl很好的協同工作mpl:模板元編程框架,包含有編譯期的算法、容器和函數等完整的元編程工具。運用mpl,很多運行時的工作都可以在編譯期完成,甚至編譯結束就意味著程序的運行結束preprocessor:預處理元編程工具,類似于模板元編程,但發生在編譯之前的預處理階段。preprocessor改變了以往人們對預處理器的看法,令人們認識到預處理也是一種強大的編程工具。preprocessor可以和模板元編程很好的配合,從而發揮更大的作用interporcess:可移植的進程間通信(IPC)功能,包括共享內存、內存映射文件、信號量、文件鎖、消息隊列等現代操作系統的IPC機制,并提供了簡潔易用的STL風格接口,大大簡化了IPC編程工作MPI:高性能分布式并行計算應用開發,封裝了標準的MPI(消息傳遞接口)以更好的支持現代C++編程風格。需要有底層MPI實現的支持,如Open MPI、MPICH等accumulators:用于增量統計的庫,也是一個用于增量計算的可擴展的累加器框架,可以看做是std::accumulate算法的擴展interval:處理“區間”相關的數學問題,把一般的算術運算和集合運算擴展到區間上math:包含大量數學領域的模板類和算法,如復數的反三角函數、最大公約數和最小公倍數、四元數、八元數、拉格朗日多項式、橢圓積分、X方分布、伯努利分布等uBLAS:用于線性代數的數學庫,優于std::valarray。STL風格,容易使用并且效率很高iostreams:擴展C++標準庫流處理的框架。定義了Source、Sink、Filter等流處理概念,使得編寫流處理更容易serialization:實現C++數據結構的持久化,可以把任意的C++對象序列化為字節流或文本。并且支持STL容器compressed_pair:與std::pair類似,使用空基類優化技術。當兩個成員之一是空類,則編譯器就會“壓縮”compressed_pair的大小以節約空間base_from_member:將成員移動到輔助基類,使用模板技術來進行成員初始化,實現子類初始化基類字段vonversion:增強C++轉型操作,提供多態對象轉型的polymorphic_cast<>、polymorphic_downcast<>和字面量轉換的lexical_cast<>flyweight:實現享元模式,享元對象是不可修改但可賦值的。numeric conversion:提供用于安全數字轉型的的一組工具,包括numeric_cast<>、bounds<>和converter<>等scope_exit:使用preprocessor庫的預處理技術實現在退出作用域時的資源自動釋放,也可以執行任意的代碼statechart:一個功能完善且強大的優先狀態自動機框架,完全支持UML語義,可以從UML模型很方便的轉換為C++代碼。比起手工構建的狀態機,可以極大的縮短開發周期,并有足夠的性能保證units:實現物理學的量綱處理,包括長度、質量、時間、電流、溫度、質量和發光強度等。使用了模板元編程技術(MPL),支持國際標準量綱,也支持其他常用的非標準量綱。所有量綱運算都在編譯時,無運行時開銷value_initialized:用于保證變量在聲明時被正確的初始化,擁有零值或缺省值utility:noncopyable、BOOST_BINARY、BOOST_CURRENT_FUNCTION等 checked_delete:編譯期保證delete或delete[]操作刪除的是一個完整類定義,以避免運行時出現未定義行為next()和prior():為迭代器提供后向和前向的通用處理方式addressof:獲得變量的真實地址,是取址符&的增強版本,對重載operator&免疫
?
第15章?Boost與設計模式
創建型模式 抽象工廠(Abstract Factory):抽象工廠模式就是把對象的創建封裝在一個類中,這個類的唯一任務就是按需生產各種對象,通過派生子類的方式抽象工廠可以產生不同系列的、整套的對象。工廠類通常是單間,以保證在系統的任何地方都可以訪問,其中的每個方法都是工廠方法。在較小的軟件系統中,抽象工廠有時候會退化成一個沒有子類的簡單工廠生成器(Builder):生成器模式分解了復雜對象的創建過程,創建過程可以被子類改變,使同樣的過程可以生產出不同的對象。生成器與抽象工廠不同,它不是一次性的創建出產品,而是分步驟逐漸的裝配出對象,因為可以對創建過程進行更精細的控制工廠方法(Factory Method):工廠方法把對象的創建封裝在一個方法中,子類可以改變工廠方法的生產行為生產不同的對象。工廠方法所屬的類不一定是一個工廠類。原型(Prototype):使用類的實例通過拷貝的方式創建對象,具體的拷貝行為可以定制。最常見的用法是實現一個clone成員函數,該函數創建一個與原型形同或相似的新對象。因C++不能高效的返回一個對象,因此實踐中很少有完全實現的原型模式,可以通過提供拷貝構造函數和operator=部分的實現原型模式單件(Singleton):保證類有且僅有一個實例,并且提供一個全局的訪問點。通常的全局變量技術雖然也可以提供類似的功能,但不能防止用戶創建多個實例。單件的基本原理很簡單,但有很多實現的變化 結構型模式 適配器(Adapter):把一個類的接口轉換(適配)為另一個接口,從而在不改變原有代碼的基礎上復用原代碼。其別名wrapper更清晰的說明了它的實現結構:包裝原有對象,再給出一個新的接口橋接(Bridge):分離了類的抽象和實現,使它們可以彼此獨立的變化而互不影響。適配器模式關心的是接口不匹配的問題,不關心接口的實現,只要求對象能夠協同工作;橋接模式的側重點是接口的實現,通常接口是穩定的,橋接解決實現的變化問題組合(Composite):將小對象組合成樹形結構,使用戶操作組合對象如同操作一個單個對象。組合模式定義了“部分-整體”的層次結構,基本對象可以被組合成更大的對象,這些組合對象與基本對象擁有相同的接口。組合是透明的,用法完全一致。裝飾(Decorator):可以在運行時動態的給對象增加功能。改變了對象的能力范圍,而且可以遞歸組合。通過生成子類的方式也可以為對象增加功能,但它是靜態的,而且大量的功能組合很容易產生“子類爆炸”現象。裝飾模式可以動態、透明的給對象增加職責,并且在不需要的時候很容易去除,使用派生子類的方式無法達到這種靈活程度。外觀(Facade):為系統中的大量對象提供一個一致的對外接口,以簡化系統的時候。外觀是另一種形式的wrapper,但不是包裝一個對象,而是包裝一組對象,簡化了這組對象間的通信關系,給出一個高層次的易用接口。外觀并不屏蔽系統里的對象,如果需要,用戶完全可以越過外觀的包裝使用底層對象以獲得更靈活的功能享元(Flyweight):使用共享的方式節約內存的使用,可以支持大量細粒度的對象。將對象的內部狀態與外部狀態分離,配合工廠模式生成僅有內部狀態的小對象,工廠內部保持小對象的引用計數從而實現共享,外部狀態可以通過計算得到。代理(Proxy):包裝并控制對象。外界不能直接訪問對象,必須通過代理才能與被包裝的對象通信。 行為模式 職責鏈(Chain of Responsibility):把對象串成鏈,使鏈上每個對象都有機會處理請求。職責鏈把請求的發送者和接收者解耦,使兩者都互不知情,而且職責鏈中的對象可以動態的增減,從而增強了處理請求的靈活性命令(Command):把請求封裝成一個對象,使請求能夠存儲更多的信息擁有更多的能力。命令模式同樣能夠把請求的發送者和接收者解耦,但并不關心請求將以何種方式被處理。命令模式經常與職責鏈模式和組合模式一起使用:職責鏈模式處理命令模式封裝的對象,組合模式可以把簡單的命令對象組合成復雜的命令對象。解釋器(Interpreter):用于實現小型語言解釋器的體系。與組合模式相似,而且常常利用組合模式來實現語法樹的構建迭代器(Iterator):將按某種順序訪問集合中元素的方式封裝在一個對象中,從而無須知道集合的內部表示就可以訪問集合中介者(Mediator):用一個中介對象封裝一系列對象的交互聯系,使他們不需要相互了解就可以協同工作。中介者模式在存在大量需要相互通信對象的系統中特別有用,因為對象數量的增加會使對象間的聯系非常復雜,整個系統變得難以理解難以改動。這時中介者可以把這些對象解耦,每個對象只需要與中介對象通信,中介對象集中控制邏輯,降低了系統的通信復雜度。中介者模式如果使用不當很容易導致中介對象過度復雜,抵消了模式帶來的好處備忘錄(Memento):捕獲一個對象的內部狀態,并在對象之外保存該狀態,在之后可以隨時把對象恢復到之前保存的狀態觀察者(Observer):觀察者模式定義了對象間一對多的聯系,當一個對象的狀態發生變化時,所有與它有聯系的觀察者對象都會得到通知。觀察者模式將被觀察者的目標和觀察者解耦,一個目標可以有任意多的觀察者,觀察者也可以觀察任意多的目標,構成復雜的聯系,而每個觀察者都不知道其他觀察者的存在狀態(State):允許對象在狀態發生變化時行為也同時發生改變。狀態轉換通常的做法是對象內部有一個值當前的狀態,根據狀態的不同使用分支來執行不同的功能。這樣會使類中存在大量結構類似的分支語句,變得難以維護和理解。狀態模式消除了分支語句,把狀態處理分散到各個狀態子類,每個子類集中處理一種狀態,使狀態的轉換清晰明確策略(Strategy):策略模式封裝了不同的“算法”。使他們可以在運行時相互替換。策略模式改變類的行為內核,而裝飾模式改變類的行為外觀。如果類的接口很龐大,那么裝飾模式的實現代價就過高,而策略模式僅改變類的內核,可能很小。模板方法(Template Method):在父類中定義操作的主要步驟,但并不實現,而是留給子類去實現。常見的用法是“鉤子操作”,父類定義了所有的公開方法,在公開方法中調用保護的鉤子方法,子類實現通過不同的鉤子方法來擴展父類的行為訪問者(Visitor):訪問者模式分離了類的內部元素與訪問他們的操作,可以在不改變內部元素的情況下增加作用于它們的新操作。如果一個類有很多內部數據,因此也就有很多訪問操作,這樣會使它的接口非常龐大,難以變動難以學習。訪問者模式可以做到數據的存儲與使用分離,不同的訪問者可以集中不同類別的操作,并且可以隨時增加新的訪問者或者新方法來增加新的操作 其他模式 空對象(Null Object):空對象模式又稱啞對象模式(Dumb Object),擴展了空指針的含義,給空指針一個默認的、可接受的行為,通常是空操作,可以說是一個“智能空指針”。使用空對象模式,程序就可以不必用條件語句專門處理空指針或類似的概念,所有的對象都會有一致的、可理解的行為。空對象模式可以和許多行為模式配合,充當“哨兵”的角色。包裝外觀(Wrapper Facade):包裝外觀模式很類似外觀模式,但包裝的目標不是一個面向對象子系統,而是底層的API。包裝外觀模式把大量的原始C接口分類整理,給外界一個統一的、面向對象的易用接口,增強了原始底層接口的內聚性。包裝外觀模式可以屏蔽系統底層的細節,有利于外界不受平臺變化的影響,增強可移植性。前攝器模式(Proactor):前攝器模式是應用于異步調用的設計模式,其核心是前攝器、異步的操作處理器、異步的事件多路分離器和完成事件隊列,可以不使用線程完成異步操作。前攝器創建一個完成處理器,用于在異步調用完成后的回調,然后發起一個異步操作,交給操作處理器異步執行,當異步操作完成時操作處理器將把時間放入完成事件隊列。前攝器調用多路分離器從完成事件隊列中獲得事件,分派事件回調完成處理器執行所需的后續操作。前攝器模式用于異步調用有很多好處,封裝了并發機制,將并發機制與線程的執行解耦,簡化了功能代碼的編寫,不需要考慮多線程的同步問題,能夠提供高性能的異步操作。缺點是模式比較復雜,處理流程難以理解和調試。
?
第16章 結束語
程序員是一個很特殊的職業,更多是用頭腦而不是用雙手來創造財富有兩種編程的方式:一種是把代碼寫的非常復雜,以至于看不出明顯的錯誤;另一種是把代碼寫的非常簡單,以至于明顯看不出錯誤注重單元測試不要重復發明輪子不能僅了解一門編程語言,這樣很容易僵化解決問題的思路方法學很重要。不一定某種方法學適合你,但可以從中汲取有用的只是,幫助你在更高的層次上看待問題進而解決問題使用好的開發工具。易用的、高效率的開發工具可以節約程序員大量寶貴的時間,把精力集中在需要處理的問題上,而不是其他易分心的事情生活中不只有C++、代碼和編程,還有更多的東西值得我們去體味。擁有美好的生活才能夠創造出完成的程序。
推薦閱讀:
《Boost 編譯》
2011-5-19
BOOST_SCOPE_EXIT可以在程序退出作用域時自動執行指定的代碼段,可以模擬finally。shared_ptr<T> ptr(p, D)也可以實現類似功能,但用BOOST_SCOPE_EXIT意圖更明確。
BOOST_SCOPE_EXIT((&connection)) // 此處&為取引用的意思,參數必須被獨立的括號包住,多個參數之間空格分隔
{
? ??connection.Close();
? ? delete?connection;
}
BOOST_SCOPE_EXIT_END;
總結
以上是生活随笔為你收集整理的boost开发指南的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。