1. 程式人生 > >Google C++ Style中允許使用的Boost庫 1

Google C++ Style中允許使用的Boost庫 1

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

write by 九天雁翎(JTianLing) -- blog.jtianling.com

新浪微博 -- 討論新聞組 -- 程式碼庫

 -- 豆瓣


前言

作為系列的第一篇,如同往常一樣嘮叨幾句吧,好久不寫這種單純語言相關的(特別是C++)文章了,因為慢慢覺得這些東西自己學學就OK,實際寫出來的價值有限,因為思想少,技巧/知識多。因為前段時間做了半年多的Object C和JAVA了,並且C++ 0x標準就要出來了,語言改變還挺大,趁這個節骨眼,順面再回頭學習/總結一些我感興趣的C++知識吧,不過應該持續時間不會太長,這個系列也不會太長,因為語言已經不是我關注的重點~~~~
Google的C++ Style Guide
是我自己寫東西的時候遵循的C++程式碼風格規範,前段時間看到李開復說他才發現Google的C++規範已經公開了,說這是世界上最好的C++規範,我感到很驚訝,因為N年前這個規範已經就公開了-_-!事實上,Google的 C++ Style Guide遠不僅是一個傳統意義上的程式碼書寫風格指導,對於C++的方方面面做出了Google的解釋和使用建議,包括每個規則給出時,較為詳細的講了這個規則好的一面和不好的一面,最最激進的規則甚至有禁用C++的異常,以及除了Google規範的Interface作為基類外,禁用多重繼承,在絕大部分情況下禁用預設引數等內容。在很大程度上,Google是想把C++打造成效率高的JAVA來使用~~~~

Google的C++ Style Guide
有關於 Boost的一節 ,允許使用的Boost庫如下:

Call Traits
 from boost/call_traits.hpp
Compressed Pair
 from boost/compressed_pair.hpp
Pointer Container
 from boost/ptr_container except serialization and wrappers for containers not in the C++03 standard (ptr_circular_buffer.hpp and ptr_unordered*)

Array
 from boost/array.hpp
The Boost Graph Library (BGL)
 from boost/graph, except serialization (adj_list_serialize.hpp) and parallel/distributed algorithms and data structures (boost/graph/parallel/* andboost/graph/distributed/*).
Property Map
 from boost/property_map, except parallel/distributed property maps (boost/property_map/parallel/*).
The part of  Iterator  that deals with defining iterators: boost/iterator/iterator_adaptor.hpp, boost/iterator/iterator_facade.hpp, and boost/function_output_iterator.hpp

對此我感到比較驚訝,除了Array沒啥好疑問的以外,我發現一些的確很好用的Boost庫Google並不允許使用,比如 boost::bind boost::function boost::lambda  等,這個我不理解~~~~而Google提及的幾個Boost庫,除了Array很簡單實用,BGL是一個數據結構和演算法的擴充庫,以前沒有接觸不奇怪外,其他的東西我發現自己竟然沒有太接觸過,作為自認為C++學習已經接近語言律師的我情何以堪-_-!~~~~~

因為很多時候,一個Boost庫就代表著一個C++的缺陷的補救,因為即使最後不用Boost庫,瞭解一下對於怎麼正確的使用C++還是有很大幫助的。特作此係列。
1. Call Traits  from boost/call_traits.hpp

先談談什麼是Traits,BS的解釋如下:
Think of a trait as a small object whose main purpose is to carry information used by another object or algorithm to determine "policy" or "implementation details". - Bjarne Stroustrup
可以參考這裡。所謂Call Traits就是呼叫時需要的Traits。  Call Traits中文文件看下基本就明白啥意思了。我感覺最大的作用是在寫模版類/模版函式傳遞引數時,保證沒有“引用的引用”的情況發生,並且總以最高效的形式傳遞引數。所謂的最高效形式的規則類似JAVA,(僅僅是類似)即原生的型別就使用傳值方式,物件就採用傳引用方式。這裡有個中文的例子 正常情況下,一個函式在C++中要麼以傳值方式傳遞引數,要麼以傳引用的方式傳遞,沒法兩者兼得: template <class T> class TestClass { public:
  TestClass(T value) {
  }
  TestClass(const T& value) {
  }      T value_; }; 在使用時會報錯: error C2668: 'TestClass<T>::TestClass' : ambiguous call to overloaded function
因為C++的函式過載規則並沒有規定在這種情況下會呼叫哪一個函式,導致二義性。 使用Call_Traits的param_type作為引數型別時,以下例子: int g_i = 0; class PrintClass { public:   PrintClass() {     printf("PrintClass created");     ++g_i;   } };
template <class T> class TestClass { public:
  TestClass(typename boost::call_traits<T>::param_type value) : value_(value){
  }   T value_; };
  TestClass<int> test(10);
  PrintClass printClass;   TestClass<PrintClass> testPrintClass(printClass);
g_i會等於1,實際因為傳遞的typename boost::call_traits<T>::param_type value在引數型別是PrintClass(一個物件)時,傳遞的是引用。同時,我沒有想到更好的辦法去驗證在傳遞的引數是int型別時,的確是通過時傳值。這樣說來就很有意思了,因為即使我們在使用模版時函式全部通過傳值方式來設計,會在T是物件時導致很大的額外開銷,我們全部通過const T&的方式來傳遞引數就好了,就算是原生型別,這種額外開銷還是小到足夠忽略不計的,只是,boost庫的製作者覺得這樣還是不夠完美? 同時,Call Traits還解決一個問題,那就是"引用的引用",比如上例中T為T&時的情況..........函式引數假如是通過傳遞引用的方式的話,const T&的引數,T又等於T&,那麼就是const T&&了,C++中沒有引用的引用這種東西的存在(只有指標的指標),事實上,Call Traits給函式的呼叫和引數的型別有完整的一套解決方案,如boost文件中的example 1: template <class T> struct contained {   // define our typedefs first, arrays are stored by value   // so value_type is not the same as result_type:   typedef typename boost::call_traits<T>::param_type       param_type;   typedef typename boost::call_traits<T>::reference        reference;   typedef typename boost::call_traits<T>::const_reference  const_reference;   typedef T                                                value_type;   typedef typename boost::call_traits<T>::value_type       result_type;
  // stored value:   value_type v_;
  // constructors:   contained() {}   contained(param_type p) : v_(p){}   // return byval:   result_type value() { return v_; }   // return by_ref:   reference get() { return v_; }   const_reference const_get()const { return v_; }   // pass value:   void call(param_type p){}
};

2.Compressed Pair from boost/compressed_pair.hpp
這裡正好找到一個很perfect的文章,簡單的說就是當pair中某個類是空類時,compressed Pair比std中的pair會更省一些空間(1個位元組...........),我幾乎沒有想到我實際工作中有什麼對空間要求非常高並且還會使用pair的情況.................這也就是compressed_pair的尷尬之處了。可以稍微提及的是,看看compressed pair的定義,就能看到call traits的使用: template <class T1, class T2> class compressed_pair { public:   typedef T1                                                 first_type;   typedef T2                                                 second_type;   typedef typename call_traits<first_type>::param_type       first_param_type;   typedef typename call_traits<second_type>::param_type      second_param_type;   typedef typename call_traits<first_type>::reference        first_reference;   typedef typename call_traits<second_type>::reference       second_reference;   typedef typename call_traits<first_type>::const_reference  first_const_reference;   typedef typename call_traits<second_type>::const_reference second_const_reference;
  compressed_pair() : base() {}   compressed_pair(first_param_type x, second_param_type y);   explicit compressed_pair(first_param_type x);   explicit compressed_pair(second_param_type y);
  compressed_pair& operator=(const compressed_pair&);
  first_reference       first();   first_const_reference first() const;
  second_reference       second();   second_const_reference second() const;
  void swap(compressed_pair& y); };
說實話,雖然邏輯上感覺完美了,但是程式碼上還真是累贅...........typedef簡直就是C++強型別+型別定義複雜最大的補丁工具.............但是總的來說compress pair是很簡單的東西,不多講。
3.Array from boost/array.hpp Array也是最簡單的boost庫使用類之一了,用於以最小效能損失替代原生C語言陣列,並且像vector一樣,提供使用的函式和合理的封裝(STL提供的vector因為是變長陣列,還是有一定的效能損失)感覺不是非常非常效率要求的工程,可以將所有的C語言陣列都用Array來代替,意義更加明確,迭代器使用也會更加方便,容器的使用語法也更加統一。另外,C++0X已經確定新增array庫,array將來就是未來的標準庫,可以較為放心的使用,並且即使使用了,也是可維護的程式碼(即使將來使用C++0X時也是一樣)。 操作示例:   boost::array<int, 100> intArray;
  intArray.fill(10);
  for (boost::array<int, 100>::iterator it = intArray.begin();     it != intArray.end(); ++it) {
      *it = 20;   }

小結: 基本上, 1.call traits是看需求了,假如你實現模板庫有需要才使用,不要因為真的僅僅為了一個函式的引數呼叫能夠以最優化的方式進行而去使用call traits。 2.comress pair是我不太推薦使用(為了一點點空間,而增加理解的難度不值,推薦的方式是將來STL的pair實現就是compress pair) 3.array是推薦使用

原則是,有利於抽象和原始碼易讀性的用,否則不用.............

原創文章作者保留版權 轉載請註明原作者 並給出連結

write by 九天雁翎(JTianLing) -- blog.jtianling.com



           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述