Boost程式庫入門學習
優秀的程式設計師要能夠知其所以然,而不是重複的造輪子,近期目標是學習優秀的第三方庫,同時嘗試使用C++11/14新特性,然後吸取精華用到專案中去,加油~
參考書籍:
羅劍鋒寫的《Boost程式庫完全開發指南》和《Boost程式庫探祕》,前者是一個大體的介紹,後者是針對一些諸如模板超程式設計等高階特性做了深入的探討。
一、Boost庫概述
Boost是一個功能強大、構造精巧、跨平臺、開源並且完全免費的C++程式庫。
C++11標準庫中有三分之二來自Boost庫,Boost庫建立在“既有的實踐”之上並提供參考實現,大大增強了C++的功能和表現力。
下載地址:
安裝:
tar -xzvf boost_1_63_0.tar.gz
cd boost_1_63_0
//編譯前配置工作
./bootstrap.sh --prefix=/usr/local
//命令b2開始真正的編譯並安裝boost
./b2 install --with=all
我們可以看到:標頭檔案安裝到了/usr/local/include,庫檔案安裝到/usr/local/lib中。
Boost庫大多陣列件不需要編譯連結,在自己的原始碼中直接包含標頭檔案即可。如果要使用boost::tribool,只需要在C++原始檔中新增如下include語句:
#include <boost/logic/tribool.hpp>
using namespace boost; //名稱空間
檔案字尾.hpp = .h + .cpp,把C++類的宣告和實現放在了一個檔案中。
剩下的少量庫(如thread,date_time)必須編譯成靜態庫或者動態庫,並在構建時指定連結選項。
補充
這裡補充一下Windows環境下如何安裝,我們假定原始碼資料夾放在桌面,資料夾名字為code,我們需要在visual studio的工程中設定編譯器搜尋路徑為:
二、Boost開發環境驗證
1) 不使用編譯庫
編寫一個簡單的Boost應用程式來驗證開發環境。
#include <boost/version.hpp>
#include <boost/config.hpp>
#include <iostream>
using namespace std;
int main()
{
cout<< BOOST_VERSION<<endl; //版本號
cout<< BOOST_LIB_VERSION<<endl;
cout<< BOOST_PLATFORM<<endl; //作業系統
cout<< BOOST_COMPILER<<endl;
cout<< BOOST_STDLIB<<endl;
}
編譯
g++ test.cpp -o test
./test
輸出
106300
1_63
linux
GNU C++ version 5.4.0 20160609
GNU libstdc++ version 20160609
2) 使用編譯庫
下面程式碼是執行緒的helloworld和timer類的使用例子。
#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/timer.hpp>
using namespace std;
using namespace boost;
void hello()
{
cout<<"hello boost"<<endl;
}
int main()
{
timer t;
boost::thread thrd(&hello);
thrd.join();
cout<<t.elapsed_max()/3600<<endl;//最大時間,單位:小時
cout<<t.elapsed_min()<<endl; //最小統計時間,單位:秒
cout<<t.elapsed()<<endl;//從建立物件開始,時間流失統計
return 0;
}
由於使用了thread庫,我們需要在連結時指定路徑,然後測試:
g++ hello.cpp -o hello -I/usr/local/include -L/usr/local/lib -lboosstem -lboost_thread
其中編譯指令選項參考之前文章編譯與連結複習,這裡需要說明的是,執行後可能出現錯誤:
我們首先檢視可執行檔案的所連結的檔案,然後查詢/usr路徑下是否有該檔案,若有說明連結設定不當,這是因為程式執行時,會在.usr/lib和/lib等目錄中查詢需要的動態庫檔案。若找到則載入動態庫檔案,否則提示類似上述錯誤。
//方法一:
LD_LIBRARY_PATH="/usr/local/lib" ./hello
//方法二:
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
sudo ldconfig
之後,執行沒有錯誤,輸出:
hello boost
2.56205e+09
1e-06
0.000381
3) progress_timer學習
progress_timer也是一個計時器,繼承自timer,會在析構時自動輸出時間,省去了timer手動呼叫elapsed()的工作。
#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/timer.hpp>
#include <boost/progress.hpp>
using namespace std;
using namespace boost;
int main()
{
//測試progress_timer
progress_timer pt;
return 0;
}
這樣,程式退出main函式作用域導致pt析構時,會自動輸出流逝的時間。
缺點:精度不夠,Linux下單位為s。
三、Boost元件progress_display
progress_display是一個獨立的類,與timer庫中其它的兩個元件-timer和progress_timer沒有任何關係。
#include <iostream>
#include <boost/progress.hpp>
#include <vector>
#include <fstream>
using namespace std;
using namespace boost;
int main()
{
vector<string> vec(1000);
ofstream fs("./test.txt"); //一個字串向量
//宣告一個progress_display物件,基數是vec的大小
progress_display pd(vec.size());
//迭代遍歷
for(auto& x:vec)
{
fs<< x<< endl; //更新進度
++pd;
}
return 0;
}
我們把一些儲存在std::vector中的字串以每個一行的形式寫入到文字檔案,由於字串數量很多,可能操作會耗費很多時間。progress能讓程式有一個友好的人機介面,讓使用者知道程式的進度。
缺陷:無法把進度顯示輸出與程式的輸出分離。
三、date_time庫概述
date_time類,可以滿足絕大多數程式對時間的要求,但是不能處理1400年以前的時間,但是它的優點是很明顯的,它允許我們更加自由地去操縱時間。