發現自己是越來越懶了,竟然原來有大半年沒有寫blog。
今天是中秋節,先祝各位看官中秋節快樂、人月兩團圓!!!!
這大半年什么都干了半桶水:javascript、HTML、servlet、JSP、php、python、COM……雖說干得不精,但也有一點點收獲……
C++論壇當然還是討論回C++。
首先推薦一本書:
《Exceptional C++ Style》Herb Sutter著
Her Sutter的多篇著作都被視為C++開發的經典教本。這本書跟《Exceptional C++》的不同在于更多地討論style。作者根據自己的經驗,對C++的編寫提出了很多準則。作者對這些準則的來龍去脈說得清清楚楚,為什么要這樣做,不做會有什么后果,在什么編譯器下面準則有什么不同的表現等等……比某人出版的C++規范,提出一堆無關痛癢不知所云的規則來的實在得多。
看完以后回顧一下自己之前的代碼,簡直汗顏,重新燃起重寫的沖動……
再說一件小事,就在看完這本書的若干天后,忽然發生一件奇事。某個程序一直編譯運行都好好的。這天換了編譯環境,程序運行不斷core dump,gdb跟了一下是說某個exception沒有catch,但是代碼里面明明寫了catch的,為什么抓不住呢。幸好看了這本書(不是賣廣告,汗),第13條……中間有某個函數的異常聲明不正確。簡單說就是函數1聲明會拋出異常A和B,但函數1里面調用了函數2,函數2會拋出異常C。于是,在調用函數1的時候盡管聲明了cacth異常C也無濟于事,C就是不能處理。(這個不是所有編譯器的標準行為)
另外收集了幾個C++ lib
QuickFunctor 看名字就知道是Functor的lib。用來做functor,signal/slot當然不在話下。有趣之處在于它實現了一些boost::bind的功能(不依賴boost,但可以和boost、loki、TR1等一起使用)。給些例子會清晰一點:
struct Car
{
string make;
string model;
int mpg;
Car(const string& make, const string& model, int mpg) : make(make), model(model), mpg(mpg) {}
};
void findCars(vector<Car>& v, const Functor<bool (Car&)>& test)
{
vector<Car>::iterator it;
it = partition(v.begin(), v.end(), test);
cout << "found " << it - v.begin() << " result(s):\n------------------\n";
for (vector<Car>::iterator it1 = v.begin(); it1 != it; ++it1)
{
cout << (*it1) << endl;
}
cout << "**************************************\n";
}
bool hasTdi(const string& s)
{
return string::npos != s.find_first_of("TDI");
}
cout << "Cars that have at least 23 mpg\n";
findCars(v, mkF(&Car::mpg) >= 23);
cout << "Cars that have the mpg between 23 and 41\n";
findCars(v, mkF(&Car::mpg) >= 23 && mkF(&Car::mpg) <= 41);
cout << "Toyotas that have at least 25 mpg\n";
findCars(v, mkF(&Car::make) == "Toyota" && mkF(&Car::mpg) >= 25);
vector<Car>::iterator it;
it = find_if(v.begin(), v.end(), mkF(hasTdi).comp<1>(mkF(&Car::model)));
// mkF(hasTdi).o(mkF(&Car::model)) is a shortcut for the test above
cout << "A car that has TDI: " << (*it) << endl;
個人覺得比boost的簡潔一些。不過boost的bind加上的lambda實在是無敵。
另外收藏一個lib是
rapidxml 其特點就是完全是C++ header,lib本身不需要編譯,除了STL不需要其他的lib,STL風格的接口。還有一個是我最想要的,對XML內容的訪問可以通過引用方式,不需要額外分配內存。舉例說,假如有一個char * p指針,并分配了一大片內存空間,在里面保存了XML的完整內容。經過parse后,我想獲得其中一個node的內容,那我可以選擇一種方式,直接引用p所指向的內存中的一部分來獲得node的內容,而不需要重新分配一段空間來保存。
以往我一直選用CMarkup作為C++的parser,目的就是圖他簡單。現在發現rapidxml后,發現rapidxml似乎比CMarkup簡單易用,更重要的是rapidxml完全開源,不像CMarkup那樣還要分不同的license。對于簡單的訪問XML,覺得這個rapidxml足夠了。
asio 說到網絡的異步響應框架,首先想到的就是ACE的proactor。但是個人一直覺得ACE是在有愧于C++,C語言的痕跡太深了,估計是“出道”太早的緣故。boost類庫遲遲沒有thread、socket方面的lib放出。asio似乎可以填補了這兩個空白。asio基于boost,類庫的風格以及提供的接口也跟boost十分相似。還是給段例子實際:
#include <ctime>
#include <iostream>
#include <string>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <asio.hpp>
using asio::ip::tcp;
std::string make_daytime_string()
{
using namespace std; // For time_t, time and ctime;
time_t now = time(0);
return ctime(&now);
}
class tcp_connection
: public boost::enable_shared_from_this<tcp_connection>
{
public:
typedef boost::shared_ptr<tcp_connection> pointer;
static pointer create(asio::io_service& io_service)
{
return pointer(new tcp_connection(io_service));
}
tcp::socket& socket()
{
return socket_;
}
void start()
{
message_ = make_daytime_string();
asio::async_write(socket_, asio::buffer(message_),
boost::bind(&tcp_connection::handle_write, shared_from_this(),
asio::placeholders::error,
asio::placeholders::bytes_transferred));
}
private:
tcp_connection(asio::io_service& io_service)
: socket_(io_service)
{
}
void handle_write(const asio::error& /*error*/,
size_t /*bytes_transferred*/)
{
}
tcp::socket socket_;
std::string message_;
};
class tcp_server
{
public:
tcp_server(asio::io_service& io_service)
: acceptor_(io_service, tcp::endpoint(tcp::v4(), 13))
{
start_accept();
}
private:
void start_accept()
{
tcp_connection::pointer new_connection =
tcp_connection::create(acceptor_.io_service());
acceptor_.async_accept(new_connection->socket(),
boost::bind(&tcp_server::handle_accept, this, new_connection,
asio::placeholders::error));
}
void handle_accept(tcp_connection::pointer new_connection,
const asio::error& error)
{
if (!error)
{
new_connection->start();
start_accept();
}
}
tcp::acceptor acceptor_;
};
int main()
{
try
{
asio::io_service io_service;
tcp_server server(io_service);
io_service.run();
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
暫時不清楚asio的性能如何。ACE經過千錘百煉,無數的應用實踐,其地位不是這么容易動搖。但asio的封裝方式是否值得ACE效仿呢。