日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

boost开发指南

發布時間:2023/12/2 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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、weeks
  • date_period表示兩個date之間的日期區間(精度到天的TimeSpan)
  • date_iterator、week_iterator、month_iterator和year_iterator是時間的迭代器
  • boost::greorian::gregorian_calendar中有實用靜態方法:is_leap_year、end_of_month_day
  • time_duration表示微妙或納秒級的時間概念,幾個實用子類:hours、minutes、seconds、millisec/milliseconds、microsec/microseconds、nanosec/nannoseconds
  • duration_from_string可以從字符串解析time_duration
  • ptime用來表示時間點,相當于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,1
  • assign支持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_comparable
  • additive:可加減概念,組合了addable和subtractable
  • multiplicative:可乘除概念,組合了multipliable和diviable
  • arithmetic:算術運算概念,組合了additive和multiplicative
  • unit_stoppable:可步進概念,組合了incrementable和decrementable
  • public 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 = 35
  • format在提供的參數過多或過少的情況下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_compare
  • all(檢測字符串中的所有元素是否滿足給定的判斷式)
  • 仿函數is_equal, is_less, is_not_greater
  • is_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、trim
  • find_first、find_last、find_nth、find_head、find_tail
  • replace/erase_first、replace/erase_last、replace/erase_nth、replace/erase_all、replace/erase_head、replace/erase_tail
  • find_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_multiset
  • boost::bimap,雙向映射容器,提供left、right兩個試圖。支持的集合類型有:set_of、multiset_of、unordered_set_of、unordered_multiset_of、list_of、vector_of、unconstrained_set_of
  • bimap的左右視圖還可以通過標簽訪問:
    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_variable
  • thread_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开发指南的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。