boost開發指南

C++確實很複雜,神同樣的0x不知道可否使C++變得純粹和乾爽?java

    boost很複雜,感受某些地方有過分設計和太過於就事論事的嫌疑,對實際開發工做的考慮太過於理想化。學習boost自己就是一個複雜度,有魄力在項目中普遍採用boost複雜度會再加一層,抓狂的編譯時間,井噴式的編譯錯誤,運行時崩潰後的咒語式堆棧……python

    其中好的東西仍是值得用的,但凡事有個度。若是將應用作到boost這個級別了,要麼你很牛,要麼你在裝。ios

    用不用,看看仍是有好處的。建議中高級以上C++程序員瞭解boost。git


第1章 Boost程序庫總論
  1. 使用Boost,將大大加強C++的功能和表現力

 

第2章 時間與日期程序員

  1. timer提供毫秒級的計時精度,內部是經過std::clock取時間的
  2. progress_timer自動打印某生命週期的執行時間
  3. 原則上程序庫的代碼是不該該被用戶修改的
  4. progress_display能夠在控制檯上顯示程序的執行進度
  5. date_time庫能很好的表示日期時間概念,並能和C的時間結構tm進行友好互轉
  6. date類提供年月日和星期幾的概念。data可經過from_string或from_undelimited_string從字符串解析而來,可經過to_simple_string、to_iso_string、to_extended_iso_string轉換爲字符串。(精度到天的DateTime
  7. day_clock是精度到天的時鐘
  8. date_duration表示的是天精度的時間間隔概念,別名爲days,另外還有years、months、weeks
  9. date_period表示兩個date之間的日期區間(精度到天的TimeSpan
  10. date_iterator、week_iterator、month_iterator和year_iterator是時間的迭代器
  11. boost::greorian::gregorian_calendar中有實用靜態方法:is_leap_year、end_of_month_day
  12. time_duration表示微妙或納秒級的時間概念,幾個實用子類:hours、minutes、seconds、millisec/milliseconds、microsec/microseconds、nanosec/nannoseconds
  13. duration_from_string能夠從字符串解析time_duration
  14. ptime用來表示時間點,至關於date和time_duration的組合。能夠用time_from_string或from_iso_string解析。(TimeSpan
    ptime now1 = second_clock::local_time(); // 獲得本地當前秒精度時間
    ptime now2 = microsec_clock::universal_time(); // 獲得本地當前微秒精度時間
  15. time_period表示兩個ptime之間的時間區間。(DateTime
  16. 時間迭代器沒有日期迭代器那麼多,只有time_iterator一個
  17. (boost時間日期庫亂、破碎、過分設計)

 

 第3章 內存管理正則表達式

  1. scoped_ptr相似auto_ptr,但其一旦得到對象的管理權,你就沒法再從它那裏取回來。該智能指針只但願在本做用域裏使用,不但願被轉讓。auto_ptr有意設計成全部權的自動轉讓,scoped_ptr有意設計成全部權的沒法轉讓。scoped_ptr和auto_ptr均不能做爲容器元素。
  2. scoped_array包裝的是new[]產生的指針,並調用的是delete[]。每每是用來和C代碼保持兼容,通常不推薦使用
  3. 不管是編譯器仍是程序員都很難區分出new[]和new分配的空間,錯誤的運用delete將致使資源異常
  4. 在C++歷史上曾經出現過無數的引用計數型智能指針實現,但沒有一個比得上boost::shared_ptr,在過去、如今和未來,它都是最好的
  5. shared_ptr支持的轉型有:static_pointer_cast<T>、const_pointer_cast<T>、dynamic_pointer_cast<T>,返回的結果是shared_ptr,並能保證這些指針的引用計數正確
  6. 用shared_ptr能夠消除代碼中顯示的delete,用make_shared、allocate_shared能夠消除代碼中顯示的new
  7. 橋接模式(bridge)是一種結構型設計模式,它把類的具體實現細節對用戶隱藏起來,以達到類之間的最小耦合關係。在具體編程實踐中橋接模式也被稱爲pimpl或者handle/body慣用法,它能夠將頭文件的依賴關係降到最小,減小編譯時間,並且能夠不使用虛函數實現多態
  8. get_deleter(shared_ptr<T> const& p)能夠得到刪除器。shared_ptr的刪除器在處理某些特殊資源時很是有用,它使得用戶能夠定製、擴展shared_ptr的行爲,使其不只僅可以管理內存資源,而是稱爲一個「萬能」的資源管理工具
  9. 對應shared_ptr,也有一個shared_array,scoped_array和shared_array均不對operator[]作下標檢測
  10. weak_ptr是爲配合shared_ptr而引入的,更像是shared_ptr的一個助手而不是智能指針,其沒有重載operator*和->,不具備普通指針的行爲。它最大的做用在於協助shared_ptr工做,像旁觀者那樣觀測資源的使用狀況
  11. weak_ptr被設計爲與shared_ptr共同工做,能夠從一個shared_ptr或者另外一個weak_ptr對象構造,得到資源的觀測權。但weak_ptr沒有共享資源,它的構造不會引發指針引用計數的增長。一樣,在weak_ptr析構時也不會致使引用計數的減小,它只是一個靜靜的觀察者
  12. 得到this指針的shared_ptr,使對象本身可以產生shared_ptr管理本身:class T : public enable_shared_from_this<T>, then shared_ptr shared_from_this().
  13. intrusive_ptr是一個侵入式的引用計數型指針。當對內存佔用的要求很是嚴格,或現存代碼已經有了引用計數機制時能夠考慮。通常狀況不推薦使用。
  14. pool爲固定塊大小的相似malloc的原生內存分配器,支持數組式分配,通常狀況下沒必要對分配的內存調用free()。只分配原生內存,不調用構造函數,回收不調用析構函數,最好不要用於對象。
  15. singleton_pool和pool接口徹底一致,但爲單件線程安全,一樣要求編譯期指定要分配的原生內存塊大小
  16. object_pool爲特定類型的對象池,不支持數組式分配,支持對象分配和對象原生內存分配
  17. pool_alloc和fast_pool_allocator是boost提供的兩個STL分配器。除非有特別需求,咱們應該總使用STL實現自帶的內存分配器。使用定製的分配器須要通過仔細的測試,以保證它與容器能夠共同工做。
  18. 內存管理是C++程序開發中永恆的話題,由於沒有GC,當心謹慎的管理內存等系統資源是每個C++程序員都必須面對的問題

 

第4章 實用工具算法

  1. private繼承自noncopyable能夠編譯時禁止對象拷貝語法
  2. C++靜態強類型的優勢有時候反而是阻礙程序員生產力的「缺陷」
  3. typeof庫使用宏模擬了C++0X中的typedef和auto關鍵字,能夠減輕書寫繁瑣的變量類型聲明工做,簡化代碼。對於用戶自定義類型須要手工用宏註冊。(語法並沒那麼好看,不許備使用)
  4. optional<T>使用「容器」語義,包裝了「可能產生無效值」的對象,實現了「未初始化」的概念(Nullable<T>
  5. optional<T> make_optional(bool condition, T const& v)用來簡單構建optional對象,但不能處理optional<T&>的狀況。(此乃雞肋) 
  6. optional<string> str(in_place("string就地建立")),而不需拷貝臨時對象,避免大對象的拷貝開銷
  7. 用於初始化的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");
  8. 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");
  9. 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";
  10. 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"))
    若是須要將括號與逗號混合使用,則要求最外側加一個括號,不然編譯器沒法推導
  11. 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")
  12. assign tuple_list_of用戶初始化元素類型爲tuple的容器
  13. 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
  14. 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();
  15. assign也支持部分不在STL中的非標準容器slist、hash_map、hash_set,由於其符合標準容器定義,同時也支持大部分boost容器:array、circular_buffer、unordered等
  16. 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);
  17. 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);
  18. 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);
  19. 單件boost::details::pool::singleton_default<T>在main以前進行構造,支持繼承或非繼承形式(最恨main以前的事情了)
  20. 單件boost::serialization::singleton<T>在main以前進行構造,支持繼承或非繼承形式。繼承方式更完全一些,非繼承方式不影響原有代碼
  21. boost::tribool三態bool,indeterminate(tribool)可判斷一個三態bool是否處於不肯定狀態
  22. 選擇optional<bool>仍是tribool:若是返回值多是無效的,那麼就是optional<bool>,若是返回值老是肯定的,但可能沒法肯定其意義,那麼就用tribool(最多本身隨手定義個enum狀態,爲了這點需求須要記住這一堆名稱和細節!)
  23. using namespace std::rel_ops; 則一旦爲類定義了operator==和<,則自動具備!=、>、<=和>=的功能。boost operators庫提供了對該功能的加強,使用時只需繼承自這些類並提供指定的operator重載便可得到附送的重載:
    1. equality_comparable<T>:要求提供==,可自動實現!=,相等語義
    2. less_than_comparable<T>:要求提供<,可自動實現>、<=、>=
    3. addable<T>:要求提供+=,可自動實現+
    4. subtractable<T>:要求提供-=,可自動實現-
    5. incrementable<T>:要求提供前置++,可自動實現後置++
    6. decrementable<T>:要求提供前置--,可自動實現後置--
    7. equivalent<T>:要求提供<,可自動實現==,等價語義
    8. totally_ordered:全序概念,組合了equality_comparable和less_than_comparable
    9. additive:可加減概念,組合了addable和subtractable
    10. multiplicative:可乘除概念,組合了multipliable和diviable
    11. arithmetic:算術運算概念,組合了additive和multiplicative
    12. unit_stoppable:可步進概念,組合了incrementable和decrementable
    13. public dereferenceable<T, P, (B)>:解引用操做符,要求提供operator*,可自動實現operator->。P爲operator->返回類型,通常爲T*
    14. public indexable<T, I, R, (B)>:下標操做符,I爲下標類型,要求可以與類型T作加法操做,一般爲int;R是operator[]的返回值類型,一般是一個類型的引用。要求提供operator+(T, I),將自動實現operator[]
  24. 若是隻關心類的等價語義,那麼就用equivalent,若是想要精確的比較兩個對象的值,就是用equality_comprable。相等equivalent基於"=="實現,而equality_comprable基於"<"的"!(x<y)&&!(x>y)"實現。
  25. 應該總對異常類是用虛繼承
  26. 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;
    }
  27. 從exception派生的異常定義很是簡單,沒有實現代碼,能夠很容易創建起一個適合本身程序的、驚喜完整的異常類體系。只要都是用虛繼承,類體系能夠任意複雜。
  28. 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;
  29. enable_error_info<T>(T& e),能夠將已將存在的任意類型包裝爲boost異常類型
  30. throw_exception(任意異常類型),能夠自動將任意異常類型包裝爲boost異常,還能保證線程安全
  31. diagnostic_information(e)能夠獲得任意boost異常的字符串內容描述;在catch塊中調用current_exception_diagnostic_information(),則不用傳參數e。(何須呢,爲少寫一兩個字母反而要記住一個更長的名字)
  32. catch塊內的異常轉型用current_exception_cast<T>()
  33. catch塊內調current_exception()獲得當前異常指針的exception_ptr是線程安全的,rethrow_exception能夠從新拋出異常
  34. UUID, Universally Unique Identifier, 128bit(16 Byte),不須要中央認證機構就能夠建立全球惟一的標識符。別名GUID
  35. 不是全部的警告均可以忽略的,有的警告預示着可能潛在的錯誤
  36. BOOST_BINARY(111 00 1),能夠實現編譯器的二進制定義,但不能超過8bit
 
第5章 字符串與文本處理
  1. lexical_cast<T>(X),能夠實現字符串和數值類型之間的轉換,但不支持高級格式控制。轉換失敗將拋出bad_lexical_cast異常。lexical_cast底層用C++流實現,要求目標類型支持operator<<、operator>>、無參構造函數和拷貝構造函數
  2. 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
  3. format在提供的參數過多或過少的狀況下operator<<或str()都會拋出異常
  4. format徹底支持printf的格式化選項方式,同時還增長了新的方式:
    1. %|spec|%:與printf格式選項功能相同,但兩邊增長了豎線分隔,能夠更好的區分格式化選項有普通字符
    2. %N%:標記第N個參數,至關於佔位符,不帶任何其餘的格式化選項
  5. format由於作了不少安全檢查工做,會比printf慢至少2-5倍
  6. format相關的高級功能:
    1. basic_format& bind_arg(int argN, const T& val) 把格式化字符串第argN位置的輸入參數固定爲val,即便調用clear()也保持不變,除非調用clear_bind()或clear_binds()
    2. basic_format& clear_bind(int argN) 取消格式化字符串第argN位置的參數綁定
    3. basic_format& clear_binds()
    4. basic_format& modify_item(int itemN, T manipulator) 設置格式化字符串第itemN位置的格式化選項,manipulator是一個boost::io::group()返回的對象
    5. boost::io::group(T1 a1, ..., Var const& var) 是一個最多支持10個參數的模板函數,能夠設置IO流操縱器以指定格式或輸入參數值
  7. string_algo庫包括:
    1. to_upper, to_lower, starts_with, ends_with, contains, equals, lexicographical_compare
    2. all(檢測字符串中的全部元素是否知足給定的判斷式)
    3. 仿函數is_equal, is_less, is_not_greater
    4. 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]內)
    5. trim_left、trim_right、trim
    6. find_first、find_last、find_nth、find_head、find_tail
    7. replace/erase_first、replace/erase_last、replace/erase_nth、replace/erase_all、replace/erase_head、replace/erase_tail
    8. find_all、split、find_iterator、split_iterator、join
  8. tokenizer相似string_algo::split,爲更專業的token劃分工具。tokenizer庫提供預約義好的四個分詞對象:
    1. char_delimiter_separator:使用標點符號分詞,是默認的分詞函數對象。已被聲明廢棄
    2. char_separator:支持一個字符集合做爲分隔符,默認行爲與char_delimiter_separator相似
    3. escaped_list_separator:用於CSV格式的分詞
    4. offset_separator:使用偏移量來分詞
  9. xpressive,相似boost.regex的正則表達式解析器,同時仍是一個相似於boost.spirit的語法分析器,而且將這兩種徹底不相交的文本處理方式完美的融合在了一塊兒
  10. xpressive使用regex_token_iterator<>提供了強大的分詞迭代器

第6章 正確性測試
  1. 測試對於軟件開發是很是重要的,程序員——尤爲是C++程序員更應該認識到這一點
  2. BOOST_ASSERT宏相似於assert宏,提供運行時斷言,但功能有所加強。能夠經過BOOST_DISABLE_ASSERTS來關閉。當定義BOOST_ENABLE_ASSERT_HANDLER後,斷言觸發時將會調用boost::assertion_failed回調
  3. BOOST_VERIFY相似BOOST_ASSERT,但斷言表達式必定會被求值,Release下仍然會失效(放棄BOOST_VERIFY)
  4. BOOST_STATIC_ASSERT,編譯時斷言。能夠出如今程序的任何位置,而不必定只在函數域內
  5. 測試用例是一個包含多個測試斷言的函數,它是能夠被獨立執行測試的最小單元,各個測試用例之間是無關的,發生的錯誤不會影響到其餘測試用例

 

第7章 容器與數據結構編程

  1. array是的C原生數組的STL接口包裝
  2. std::vector<bool>是vector對bool的特化,內部保存的實際爲bit,支持動態長度。std::bitset大小固定,但支持更多的位運算
  3. boost.dynamic_bitset相似std::vector<bool>能夠動態長度,同時提供了豐富的位運算。dynamic_bitset還支持集合相關操做
  4. 哈希容器:boost::unordered_map、boost::unordered_set、boost::unordered_multimap、boost::unordered_multiset
  5. boost::bimap,雙向映射容器,提供left、right兩個試圖。支持的集合類型有:set_of、multiset_of、unordered_set_of、unordered_multiset_of、list_of、vector_of、unconstrained_set_of
  6. 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)); // 至關於使用右視圖
  7. circular_buffer<T>爲大小固定的循環緩衝區,circular_buffer_space_optimized<T>相似circular_buffer<T>但只在確實須要時才分配內存,而且當容器內元素減小時自動釋放內存
  8. tuple是固定數目非同質元素容器。tuple是std::pair的泛化,能夠從函數返回任意數量的值,也能夠代替struct組合數據
  9. 和std::make_pair對應,也有個make_tuple用來簡化tuple的建立
  10. tie()能夠生成一個元素類型全是引用的tuple,至關於make_tuple(ref(a), ref(b), ...),能夠用於左值,一般用來接收返回tuple或pair函數的返回值,能夠當作是對tuple的解包
  11. element<N, T>::type能夠給出T中第N個元素的類型,length<T>::value能夠給出T的元素數量
  12. any可以容納任意類型,能夠用any_cast<T>(a)類型安全的取出any中的值(讓人聯想到Ogre::Any)
  13. any能夠持有原始指針,但這樣的用法很不安全,會致使內存泄露。應該使用智能指針包裝原始指針,這樣在any析構時智能指針會自動的調用delete,從而安全的釋放資源
  14. 若是但願一種數據結構具備tuple那樣的容納任意類型的能力,又能夠在運行時動態變化大小,那麼就能夠用any做爲元素類型搭配容器
  15. variant是對C/C++中union概念的加強和擴展。varinat是有界類型,元素類型範圍由用戶指定,any是無界類型,能夠容納任意類型
  16. multi_array<int, 3>,至關於int ma[X][Y][Z]的多維數組。multi_array沒有異常機制來處理錯誤,保證數組範圍不越界是庫用戶本身的責任
  17. property_tree是一個保存了多個屬性值的樹形數據結構,能夠用相似路徑的簡單方式訪問任意節點的樹形,並且每一個節點均可以用相似STL的風格遍歷子節點。property_tree特別適合於應用程序的配置數據處理,能夠解析xml、ini、json和info四種格式的文本數據,使用它能減輕本身開發配置管理的工做。

 

第8章 算法json

  1. boost foreach庫提供BOOST_FOREACH和BOOST_REVERSE_FOREACH來實現對容器的正向和反向遍歷
  2. minmax(a, b)可在一次處理中同時得到最大最小值,執行效率上有很大提升(有提早優化的感受了)
  3. minmax_element算法族能夠獲得迭代器區間內的最大最小值

 

第9章 數學與數字windows

  1. 從純數學的角度看,程序也不過是一個很是大的整數而已
  2. integer_traits : public std::numeric_limits,提供各類整數類型的編譯期最大最小值
  3. <boost/cstdint.hpp>基於C99標準中的<stdint.h>,定義了各類標準的整數
  4. <boost/integer.hpp>與<boost/cstdint.hpp>功能相似,用模板類而不是typedef提供各類整數類型定義
  5. boost.rational表示有理數(分數),rational_cast<R>能夠將有理數轉換爲普通數字
  6. 最大公約數gcd();最小公倍數lcm()
  7. crc_optimal以字節爲單位的快速CRC計算,實際經常使用的是crc_32_type的預約義算法
  8. boost random庫提供了26個僞隨機數發生器
  9. random庫提供的隨機數分佈器:
    1. uniform_smallint:在小整數域內的均勻分佈
    2. uniform_int:在整數域上的均勻分佈
    3. uniform_01:在區間[0,1]上的實數連續均勻分佈
    4. uniform_real:在區間[min,max]上的實數連續均勻分佈
    5. bernoulli_distribution:伯努利分佈
    6. binomial_distribution:二項分佈
    7. cauchy_distribution:柯西(洛倫茲)分佈
    8. gamma_distribution:伽馬分佈
    9. poisson_distribution:泊松分佈
    10. geometric_distribution:幾何分佈
    11. triangle_distribution:三角分佈
    12. exponential_distribution:指數分佈
    13. normal_distribution:正態分佈
    14. lognormal_distribution:對數正態分佈
    15. uniform_on_sphere:球面均勻分佈
  10. variate_generator<Engine, Distribution>變量發生器,用於組合隨機數發生器和分佈器
  11. 真隨機數沒法用純軟件產生,由於計算機自己是個肯定的有限狀態自動機

 

第10章 操做系統相關

  1. io_state_savers庫能夠簡化恢復流狀態的工做,它可以保存流的當前狀態,自動恢復流的狀態或者由程序員控制恢復的時機
    1. 基本的標準屬性保存器:ios_flags_saver、ios_width_saver
    2. 加強的標準屬性保存器:ios_iostate_saver、ios_rdbuf_saver
    3. 自定義的屬性保存器:ios_iword_saver、ios_pword_saver
    4. 組合的屬性保存器:ios_all_saver
  2. system庫使用輕量級的對象封裝了操做系統底層的錯誤代碼和錯誤信息,使調用操做系統功能的程序能夠被很容易的移植到其餘操做系統
    filesystem庫中的path和wpath提供了文件路徑相關的不少實用操做(相似Path)
  3. portable_posix_name()和windows_name()分別檢測文教案名字符串是否符合POSIX和Windows規範。Windows的文件名能夠字符範圍比POSIX的大。
  4. native()判斷文件名是否符合本地文件系統命名規則
  5. 爲了程序的健壯性,應總使用try-catch來保護文件訪問代碼
  6. directory_iterator和wdirectory_iterator提供了迭代一個目錄下全部文件的功能
  7. recursive_directory_iterator和wrecursive_directory_iterator提供遞歸遍歷目錄功能
  8. program_options庫提供了強大的命令行參數處理功能,它不只可以分析命令行,也可以從配置文件甚至環境變量中獲取參數,實現了很是完善的程序配置選項處理功能
  9. #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; }
    }
  10. program_options庫的解析程序選項功能由三個基本組件構成,分別是選項描述器、分析器和存儲器。選項描述其定義選項及選項的值,分析器依據選項描述器的定義解析命令行或數據文件,存儲器則把分析器的結果保存起來以供使用
 
第11章 函數與回調
  1. result_of<Func(T1, T2)>::type肯定一個調用表達式的返回類型,是實現泛型庫的底層基本構件
  2. ref()和cref()能夠包裝對象的引用,在傳遞參數時消除對象拷貝的代價,或者將不可拷貝的對象變爲能夠拷貝
  3. bind是對標準庫bind1st、bind2nd的泛化和加強,能夠適配任意的可調用對象。
  4. bind第一個參數必須是一個可調用對象,包括函數、函數指針、函數對象和成員函數指針
  5. bind也能夠綁定到public成員變量,用法與綁定成員函數相似,只須要把成員變量名像一個成員函數同樣去使用
  6. bind綁定到仿函數時,要求仿函數typedef xxx result_type;不然就只能用bind<xxx>(functor())的形式
  7. 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
  8. 變長參數函數、__stdcall、__fastcall、extern "C"等函數bind時須要顯式指定返回值類型才行
  9. function是一個函數對象的「容器」,概念上像是C/C++中的函數指針類型的泛化,是一種「智能函數指針」
  10. 調用空的function將拋出bad_function_call異常,最好在使用前經過empty()來測試有效性
  11. 與原始的函數指針相比,function對象的體積要稍微大一點(3個指針的大小),速度要稍微慢一點(10%左右的性能差距),但這與它帶給程序的巨大好處相比是無足輕重的
  12. signals2基於boost中的另外一個庫signals,實現了線程安全的觀察者模式。在signals2庫中,觀察者模式被稱爲信號/插槽(sinals and slots),它是一種函數回調機制,一個信號關聯了多個插槽,當信號發出時,全部關聯它的插槽都會被調用
  13. signal是不可拷貝的,若是把signal做爲自定義類的成員變量,那麼自定義類也將是不可拷貝的,除非用shared_ptr來包裝
  14. signal.connection()鏈接插槽時,會返回一個connection對象,能夠用來管理信號和插槽之間的鏈接關係
  15. signal2庫使用slot類提供了自動鏈接管理的功能,可以自動跟蹤插槽的生命週期,但插槽失效時會自動斷開鏈接
  16. 較之signals,signals2具備線程安全,可以用於多線程環境,並且不須要編譯就可使用

 

第12章 併發編程

  1. thread庫提供的互斥量:
    1. mutex:獨佔式互斥量
    2. timed_mutex:提供超時鎖定功能的獨佔式互斥量
    3. recursive_mutex:遞歸式互斥量,能夠屢次鎖定,相應的也要屢次解鎖
    4. recursive_timed_mutex:提供超時鎖定功能的遞歸式互斥量
    5. shared_mutex:multiple-reader/single-writer型的共享互斥量(讀寫鎖)
  2. scoped_lock和scoped_try_lock能夠在退出做用域時確保unlock的調用
  3. <boost/detail/atomic_count.hpp>提供了一個原子計數器——atomic_count,使用long進行線程安全的遞增遞減計數
  4. 信號量:condition_variable_any和condition_variable
  5. thread_group提供一個簡單的線程池,能夠對一組線程統一操做
  6. 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
    }
  7. 爲了支持多個future對象的使用,future還提供wait_for_any()和wait_for_all()兩個自由函數,他們能夠阻塞等待多個future對象,知道任意一個或者全部future對象均可用(is_ready())
  8. 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;
    }
  9. thread庫提供了兩個自由函數lock()和try_lock(),能夠一次鎖定多個互斥量,而且不會出現死鎖
    lock(mu1, mu2);
    ...;
    mu1.unlock(); // 逐個解鎖
    mu2.unlock();
  10. 多線程僅執行一次初始化須要使用一個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秒鐘
    }
  11. barrier(護欄)可用於多個線程同步,當線程執行到barrier時必須等待,直到全部的線程都達到這個點時才能繼續執行。
  12. 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;
    }
  13. this_thread名字空間下提供了at_thread_exit(func),容許註冊一個線程結束回調,不管線程是否被中斷。但線程意外終止的狀況下,該回調不會被執行
  14. promise和packaged_task都支持回調函數,可讓future延後在須要的時候得到值,而沒必要主動啓動線程計算
  15. asio庫基於OS提供的異步機制,採用前攝器設計模式(Proactor)實現了可移植的異步或同步IO操做,並且並不要求使用多線程和鎖。目前asio主要關注與網絡通訊方面,支持TCP、ICMP、UDP等網絡通訊協議,還支持串口讀寫、定時器、SSL等功能。asio是一個很好的富有彈性的框架,能夠擴展到其餘有異步操做須要的領域。
  16. asio庫基於前攝器模式(Proactor)封裝了OS的select、poll/epoll、kqueue、overlapped I/O等機制,實現了異步IO模型。它的核心類是io_service,至關於前攝器模式中的Proactor角色,asio的任何操做都須要有io_service的參數與。
    1. 在同步模式下,程序發起一個IO操做,向io_service提交請求,io_service把操做轉交給OS,同步的等待。當IO操做完成時,OS通知io_service,而後io_service再把結果發回給程序,完成整個同步流程。
    2. 異步模式下,程序出了要發起IO操做,還要定義一個用於回調的完成處理函數。io_service一樣把IO操做轉交給操做系統執行,但它不一樣步等待,而是當即返回。調用io_service的run()成員函數能夠等待異步操做完成,當異步操做完成時io_service從OS獲取操做結果,調用完成處理函數
    3. asio不直接使用OS提供的線程,而是定義了strand以保證在多線程環境中無需使用互斥量。io_service::strand::wrap()能夠包裝一個函數在strand中執行
    4. asio提供了mutable_buffer和const_buffer兩種可安全用於異步讀寫的緩衝區
  17. ip::address表示IP地址,能夠同時支持ipv4和ipv6兩種地址
  18. ip::tcp::endpoint表示ip地址和端口號
  19. 同步socket示例:
    1. 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; }
      }
    2. 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();
      }
  20. 一般客戶端不須要異步通訊
  21. resolver可實現域名解析
  22. interprocess能夠處理進程間通訊(IPC)

 

第13章 編程語言支持

  1. 任何程序開發語言都不可能獨當一面、包打天下,總有它的長處與短處
  2. python庫可以在C++中調用Python語言,但它更重要的功能在於用C++編寫Python擴展模塊,嵌入到Python解釋器中調用,提升Python的執行效率
  3. C++中的構造函數不一樣於普通的成員函數,不能取其地址

 

第14章 其餘Boost組件

  1. regex:須要編譯才能使用的正則庫
  2. sprit:面向對象的遞歸降低解析器生成框架,使用EBNF語法
  3. gil:有Adobe贊助開發的通用圖像庫。爲像素、色彩、通道等圖像處理概念提供了泛型的、STL式的容器和算法,能夠對圖像作灰度化、梯度、均值、選裝等運算。支持jpg、png、tiff等格式
  4. graph:處理離散數學中的圖結構,並提供圖、矩陣等數據結構上的泛型算法。能夠看作是STL在非線性容器領域的擴展。
  5. intrusive:侵入式容器。STL爲非侵入式容器,不須要對容器內的元素類型作修改便可容納
  6. pointer container:提供了與STL相似的若干種指針容器,性能較好且異常安全。用STL+shared_ptr也能夠作變通。
  7. multi_index:實現具備多個STL兼容訪問接口(索引)的容器
  8. iterators:定義一組基於STL的新迭代器概念、構造框架和游泳的適配器,可以用來更輕鬆的實現迭代器模式
  9. range:基於STL迭代器提出的「範圍」概念,是一個容器的半開區間,使用range可讓代碼更加簡單漂亮
  10. lambda:引入lambda表達式和函數式編程,能夠就地建立小型的函數對象,避免函數定義離調用點太遠,更方便代碼維護。lambda表達式是一種新的編程範式,但其語法十分複雜,若是使用的很差很容易寫出過於晦澀難懂的代碼,使程序難以維護。
  11. signals:觀察者模式。功能和用法與signals2基本相同,非線程安全,須要編譯。若是沒有什麼特殊理由,應該使用signals2庫
  12. enable_if:容許模板函數或者模板類在偏特化時僅針對某些特定類型有效,依賴於SFINAE(substitution failure is not an error)原則
  13. call_traits:封裝了多是最好的傳遞參數給函數的方式,它會自動推導出最高效的傳遞參數傳遞類型
  14. type_traits:提供一組trait類,用以在編譯器肯定類型是否具備某些特徵。使用type_traits能夠編寫出更好更高效的泛型代碼
  15. concept check:編譯器檢查模板函數或模板類的模板參數是否符合某個概念,是否運行進行模板參數推演。主要用來編寫泛型算法或實現泛型庫
  16. function_types:提供對函數、函數指針、函數引用和成員指針等類型進行分類、分解和合並的功能
  17. in_place_factory:直接構造對象而不須要一個臨時對象的拷貝
  18. proto:容許在C++中構建專用領域嵌入式語言,基於表達式模板技術定義小型專用語言的「編譯器」
  19. property map:提供key-value映射的屬性概念定義
  20. fusion:提供基於tuple的容器和算法,是模板元編程的強大工具,能夠與mpl很好的協同工做
  21. mpl:模板元編程框架,包含有編譯期的算法、容器和函數等完整的元編程工具。運用mpl,不少運行時的工做均可以在編譯期完成,甚至編譯結束就意味着程序的運行結束
  22. preprocessor:預處理元編程工具,相似於模板元編程,但發生在編譯以前的預處理階段。preprocessor改變了以往人們對預處理器的見解,使人們認識到預處理也是一種強大的編程工具。preprocessor能夠和模板元編程很好的配合,從而發揮更大的做用
  23. interporcess:可移植的進程間通訊(IPC)功能,包括共享內存、內存映射文件、信號量、文件鎖、消息隊列等現代操做系統的IPC機制,並提供了簡潔易用的STL風格接口,大大簡化了IPC編程工做
  24. MPI:高性能分佈式並行計算應用開發,封裝了標準的MPI(消息傳遞接口)以更好的支持現代C++編程風格。須要有底層MPI實現的支持,如Open MPI、MPICH等
  25. accumulators:用於增量統計的庫,也是一個用於增量計算的可擴展的累加器框架,能夠看作是std::accumulate算法的擴展
  26. interval:處理「區間」相關的數學問題,把通常的算術運算和集合運算擴展到區間上
  27. math:包含大量數學領域的模板類和算法,如複數的反三角函數、最大公約數和最小公倍數、四元數、八元數、拉格朗日多項式、橢圓積分、X方分佈、伯努利分佈等
  28. uBLAS:用於線性代數的數學庫,優於std::valarray。STL風格,容易使用而且效率很高
  29. iostreams:擴展C++標準庫流處理的框架。定義了Source、Sink、Filter等流處理概念,使得編寫流處理更容易
  30. serialization:實現C++數據結構的持久化,能夠把任意的C++對象序列化爲字節流或文本。而且支持STL容器
  31. compressed_pair:與std::pair相似,使用空基類優化技術。當兩個成員之一是空類,則編譯器就會「壓縮」compressed_pair的大小以節約空間
  32. base_from_member:將成員移動到輔助基類,使用模板技術來進行成員初始化,實現子類初始化基類字段
  33. vonversion:加強C++轉型操做,提供多態對象轉型的polymorphic_cast<>、polymorphic_downcast<>和字面量轉換的lexical_cast<>
  34. flyweight:實現享元模式,享元對象是不可修改但可賦值的。
  35. numeric conversion:提供用於安全數字轉型的的一組工具,包括numeric_cast<>、bounds<>和converter<>等
  36. scope_exit:使用preprocessor庫的預處理技術實如今退出做用域時的資源自動釋放,也能夠執行任意的代碼
  37. statechart:一個功能完善且強大的優先狀態自動機框架,徹底支持UML語義,能夠從UML模型很方便的轉換爲C++代碼。比起手工構建的狀態機,能夠極大的縮短開發週期,並有足夠的性能保證
  38. units:實現物理學的量綱處理,包括長度、質量、時間、電流、溫度、質量和發光強度等。使用了模板元編程技術(MPL),支持國際標準量綱,也支持其餘經常使用的非標準量綱。全部量綱運算都在編譯時,無運行時開銷
  39. value_initialized:用於保證變量在聲明時被正確的初始化,擁有零值或缺省值
  40. utility:noncopyable、BOOST_BINARY、BOOST_CURRENT_FUNCTION等
    1. checked_delete:編譯期保證delete或delete[]操做刪除的是一個完整類定義,以免運行時出現未定義行爲
    2. next()和prior():爲迭代器提供後向和前向的通用處理方式
    3. addressof:得到變量的真實地址,是取址符&的加強版本,對重載operator&免疫

 

第15章 Boost與設計模式

  1. 建立型模式
    1. 抽象工廠(Abstract Factory):抽象工廠模式就是把對象的建立封裝在一個類中,這個類的惟一任務就是按需生產各類對象,經過派生子類的方式抽象工廠能夠產生不一樣系列的、整套的對象。工廠類一般是單間,以保證在系統的任何地方均可以訪問,其中的每一個方法都是工廠方法。在較小的軟件系統中,抽象工廠有時候會退化成一個沒有子類的簡單工廠
    2. 生成器(Builder):生成器模式分解了複雜對象的建立過程,建立過程能夠被子類改變,使一樣的過程能夠生產出不一樣的對象。生成器與抽象工廠不一樣,它不是一次性的建立出產品,而是分步驟逐漸的裝配出對象,由於能夠對建立過程進行更精細的控制
    3. 工廠方法(Factory Method):工廠方法把對象的建立封裝在一個方法中,子類能夠改變工廠方法的生產行爲生產不一樣的對象。工廠方法所屬的類不必定是一個工廠類。
    4. 原型(Prototype):使用類的實例經過拷貝的方式建立對象,具體的拷貝行爲能夠定製。最多見的用法是實現一個clone成員函數,該函數建立一個與原型形同或類似的新對象。因C++不能高效的返回一個對象,所以實踐中不多有徹底實現的原型模式,能夠經過提供拷貝構造函數和operator=部分的實現原型模式
    5. 單件(Singleton):保證類有且僅有一個實例,而且提供一個全局的訪問點。一般的全局變量技術雖然也能夠提供相似的功能,但不能防止用戶建立多個實例。單件的基本原理很簡單,但有不少實現的變化
  2. 結構型模式
    1. 適配器(Adapter):把一個類的接口轉換(適配)爲另外一個接口,從而在不改變原有代碼的基礎上覆用原代碼。其別名wrapper更清晰的說明了它的實現結構:包裝原有對象,再給出一個新的接口
    2. 橋接(Bridge):分離了類的抽象和實現,使它們能夠彼此獨立的變化而互不影響。適配器模式關心的是接口不匹配的問題,不關心接口的實現,只要求對象可以協同工做;橋接模式的側重點是接口的實現,一般接口是穩定的,橋接解決實現的變化問題
    3. 組合(Composite):將小對象組合成樹形結構,使用戶操做組合對象如同操做一個單個對象。組合模式定義了「部分-總體」的層次結構,基本對象能夠被組合成更大的對象,這些組合對象與基本對象擁有相同的接口。組合是透明的,用法徹底一致。
    4. 裝飾(Decorator):能夠在運行時動態的給對象增長功能。改變了對象的能力範圍,並且能夠遞歸組合。經過生成子類的方式也能夠爲對象增長功能,但它是靜態的,並且大量的功能組合很容易產生「子類爆炸」現象。裝飾模式能夠動態、透明的給對象增長職責,而且在不須要的時候很容易去除,使用派生子類的方式沒法達到這種靈活程度。
    5. 外觀(Facade):爲系統中的大量對象提供一個一致的對外接口,以簡化系統的時候。外觀是另外一種形式的wrapper,但不是包裝一個對象,而是包裝一組對象,簡化了這組對象間的通訊關係,給出一個高層次的易用接口。外觀並不屏蔽系統裏的對象,若是須要,用戶徹底能夠越過外觀的包裝使用底層對象以得到更靈活的功能
    6. 享元(Flyweight):使用共享的方式節約內存的使用,能夠支持大量細粒度的對象。將對象的內部狀態與外部狀態分離,配合工廠模式生成僅有內部狀態的小對象,工廠內部保持小對象的引用計數從而實現共享,外部狀態能夠經過計算獲得。
    7. 代理(Proxy):包裝並控制對象。外界不能直接訪問對象,必須經過代理才能與被包裝的對象通訊。
  3. 行爲模式
    1. 職責鏈(Chain of Responsibility):把對象串成鏈,使鏈上每一個對象都有機會處理請求。職責鏈把請求的發送者和接收者解耦,使二者都互不知情,並且職責鏈中的對象能夠動態的增減,從而加強了處理請求的靈活性
    2. 命令(Command):把請求封裝成一個對象,使請求可以存儲更多的信息擁有更多的能力。命令模式一樣可以把請求的發送者和接收者解耦,但並不關心請求將以何種方式被處理。命令模式常常與職責鏈模式和組合模式一塊兒使用:職責鏈模式處理命令模式封裝的對象,組合模式能夠把簡單的命令對象組合成複雜的命令對象。
    3. 解釋器(Interpreter):用於實現小型語言解釋器的體系。與組合模式類似,並且經常利用組合模式來實現語法樹的構建
    4. 迭代器(Iterator):將按某種順序訪問集合中元素的方式封裝在一個對象中,從而無須知道集合的內部表示就能夠訪問集合
    5. 中介者(Mediator):用一箇中介對象封裝一系列對象的交互聯繫,使他們不須要相互瞭解就能夠協同工做。中介者模式在存在大量須要相互通訊對象的系統中特別有用,由於對象數量的增長會使對象間的聯繫很是複雜,整個系統變得難以理解難以改動。這時中介者能夠把這些對象解耦,每一個對象只須要與中介對象通訊,中介對象集中控制邏輯,下降了系統的通訊複雜度。中介者模式若是使用不當很容易致使中介對象過分複雜,抵消了模式帶來的好處
    6. 備忘錄(Memento):捕獲一個對象的內部狀態,並在對象以外保存該狀態,在以後能夠隨時把對象恢復到以前保存的狀態
    7. 觀察者(Observer):觀察者模式定義了對象間一對多的聯繫,當一個對象的狀態發生變化時,全部與它有聯繫的觀察者對象都會獲得通知。觀察者模式將被觀察者的目標和觀察者解耦,一個目標能夠有任意多的觀察者,觀察者也能夠觀察任意多的目標,構成複雜的聯繫,而每一個觀察者都不知道其餘觀察者的存在
    8. 狀態(State):容許對象在狀態發生變化時行爲也同時發生改變。狀態轉換一般的作法是對象內部有一個值當前的狀態,根據狀態的不一樣使用分支來執行不一樣的功能。這樣會使類中存在大量結構相似的分支語句,變得難以維護和理解。狀態模式消除了分支語句,把狀態處理分散到各個狀態子類,每一個子類集中處理一種狀態,使狀態的轉換清晰明確
    9. 策略(Strategy):策略模式封裝了不一樣的「算法」。使他們能夠在運行時相互替換。策略模式改變類的行爲內核,而裝飾模式改變類的行爲外觀。若是類的接口很龐大,那麼裝飾模式的實現代價就太高,而策略模式僅改變類的內核,可能很小。
    10. 模板方法(Template Method):在父類中定義操做的主要步驟,但並不實現,而是留給子類去實現。常見的用法是「鉤子操做」,父類定義了全部的公開方法,在公開方法中調用保護的鉤子方法,子類實現經過不一樣的鉤子方法來擴展父類的行爲
    11. 訪問者(Visitor):訪問者模式分離了類的內部元素與訪問他們的操做,能夠在不改變內部元素的狀況下增長做用於它們的新操做。若是一個類有不少內部數據,所以也就有不少訪問操做,這樣會使它的接口很是龐大,難以變更難以學習。訪問者模式能夠作到數據的存儲與使用分離,不一樣的訪問者能夠集中不一樣類別的操做,而且能夠隨時增長新的訪問者或者新方法來增長新的操做
  4. 其餘模式
    1. 空對象(Null Object):空對象模式又稱啞對象模式(Dumb Object),擴展了空指針的含義,給空指針一個默認的、可接受的行爲,一般是空操做,能夠說是一個「智能空指針」。使用空對象模式,程序就能夠沒必要用條件語句專門處理空指針或相似的概念,全部的對象都會有一致的、可理解的行爲。空對象模式能夠和許多行爲模式配合,充當「哨兵」的角色。
    2. 包裝外觀(Wrapper Facade):包裝外觀模式很相似外觀模式,但包裝的目標不是一個面向對象子系統,而是底層的API。包裝外觀模式把大量的原始C接口分類整理,給外界一個統一的、面向對象的易用接口,加強了原始底層接口的內聚性。包裝外觀模式能夠屏蔽系統底層的細節,有利於外界不受平臺變化的影響,加強可移植性。
    3. 前攝器模式(Proactor):前攝器模式是應用於異步調用的設計模式,其核心是前攝器、異步的操做處理器、異步的事件多路分離器和完成事件隊列,能夠不使用線程完成異步操做。前攝器建立一個完成處理器,用於在異步調用完成後的回調,而後發起一個異步操做,交給操做處理器異步執行,當異步操做完成時操做處理器將把時間放入完成事件隊列。前攝器調用多路分離器從完成事件隊列中得到事件,分派事件回調完成處理器執行所需的後續操做。前攝器模式用於異步調用有不少好處,封裝了併發機制,將併發機制與線程的執行解耦,簡化了功能代碼的編寫,不須要考慮多線程的同步問題,可以提供高性能的異步操做。缺點是模式比較複雜,處理流程難以理解和調試。

 

第16章 結束語

  1. 程序員是一個很特殊的職業,更可能是用頭腦而不是用雙手來創造財富
  2. 有兩種編程的方式:一種是把代碼寫的很是複雜,以致於看不出明顯的錯誤;另外一種是把代碼寫的很是簡單,以致於明顯看不出錯誤
  3. 注重單元測試
  4. 不要重複發明輪子
  5. 不能僅瞭解一門編程語言,這樣很容易僵化解決問題的思路
  6. 方法學很重要。不必定某種方法學適合你,但能夠從中汲取有用的只是,幫助你在更高的層次上看待問題進而解決問題
  7. 使用好的開發工具。易用的、高效率的開發工具能夠節約程序員大量寶貴的時間,把精力集中在須要處理的問題上,而不是其餘易分心的事情
  8. 生活中不僅有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;
相關文章
相關標籤/搜索