Monday, September 03, 2007

STL和O-O - 并非完美性伴侣

通過對STL的創造者之一Alexander Stepanov的采訪文章(http://www.stepanovpapers.com/)可以瞭解到,Stepanov對Object-Orientation這種編程paradigm是持懷疑態度的。的確,在生活中,我們能感受到STL在C++与O-O的配合幷非完美,以下是兩個例子:

1.STL container要求它元素必須是assignable的-往contrainer里塞東西的時候,要給insert(或者push_back等,最終都是調用insert的)一個object,然後insert再按照這個對象copy construction一個。如果能直接把ctor的parameters傳給insert,再有insert直接在contrainer的內存里調用ctor構造出一個元素,效率將會更高。比如:
class T
{
public:
T() {...}
T(const T&) {...}
};
要往vector v中插入一個T,必須這樣:
v.push_back(T());
這會帶來兩個copy ctor的額外開銷。理想的方式是這樣:
v.push_back()
可惜這樣的push_back沒有辦法在C++中定義。

2.O-O最主要的工具是class hierarchy,但是一組sub classes却不能直接放入一個STL container,因爲STL container都是homogeneous的。通常的做法是container容納base type的指針,但這樣做有兩個缺點:
  1. 要自己new和delete對象了。人人都知道,干這種事很容易出錯
  2. 竟然放弃STL的內存分配功能不用,如果你看過SGI STL的內存分配代碼的話,你就知道,這就是“暴殄天物”
理想的容器應該是這樣:
class Base {...}
class Sub1 : public Base {...}
class Sub2 : public Base {...}

hierarchy_vector v;
v的iterator在dereference以後還是Base*類型(不是Base*&),因爲hierarchy_vector并不知道每個元素是什麽類型。
插入元素:
v.push_back(x);
v.push_back(y);
有兩點需要注意:
  1. hierarchy_vector必須爲數組的每個元素保留max{sizeof(Sub1), sizeof(Sub2)}的空間,遮意味著一些浪費,在heap中new出一個對象同樣有額外開銷,所以hierachy_vector的效率不一定更低
  2. 可能需要在Base中定義virtual assignment operator
就現在Standard C++中的STL而言,我覺得還是堅持container只容納plain old object為好,特別避免把copy ctor,default ctor,destructor中有side effects和較大開銷的類型的對象裝入container。

No comments: