描述:
stl(指vs2008的stl)中的vector在分配物件的時候,出現一些意想不到的事情.
比如:class a
{};vectora(10);
這樣就可以構造出乙個有10個元素型別為a的vector, 考察其構造過程,就會發現其實並不是構造了10個a,而是構造了11個a,然後再析構1個.
這個主要是實現的問題,看原始碼就知道,
explicit vector(size_type _count)
: _mybase()
void _construct_n(size_type _count, const _ty& _val)
因為_construct_n在構造過程中要呼叫class a 的拷貝建構函式,所以第2個引數為乙個_ty型別,也就是上面的class a,的乙個例項.
於是就先構造出乙個臨時的a,傳給_construct_n,建構函式完成後,析構掉.
感覺主要原因實現時偷懶了吧. 可以在alloc裡面增加乙個使用 ::new(_p) _ty() (預設建構函式)的函式就好了,為什麼非要用 ::new(_p) _ty(_val) (拷貝建構函式) 呢.
同樣的問題,就是在
vectorx(10);
vectory = x;
這個時候y=x呼叫的是vector的拷貝建構函式,按照c++的"習慣",容器裡面的物件也應該使用拷貝建構函式構造,但是不幸的是由於實現的時候是用copy(x.begin(), x.end(), y.begin()) 的,所以就全部用 operator= 來做了.
首先可以看到這是兩個問題,第乙個問題,我看了sgi stl和c++標準確實是這樣實現的,並沒有提供對預設建構函式的placement new。
c++ standard 20.4.1.1
void construct(pointer p, const_reference val);
returns: new((void *)p) t(val)
但是c++標準描述的是defaultallocator,但是使用者可以自己開發allocator。那麼問題就是c++標準為什麼這樣定義?
我覺得是因為效能,有人認為多了一次預設構造會造成效能下降,其實stl考慮的是給使用者copy on write的機會。如果stl容器中插入的是帶有引用計數功能的物件。那麼拷貝建構函式就會比構造乙個新的物件快很多。因為物件內部的成員函式不需要進行分配記憶體和初始化,只是引用計數發生變化而已。cstring就是這樣實現的。具體參見more effective c++或者 exceptional c++ 和msdn。
關於第二個問題,我覺得是為了保證強烈異常安全。
vectorx(10);
vectory = x;
將拷貝構造分為兩步
1 構造y中的物件,分配記憶體初始化。
2 用operator =進行賦值。
y分配記憶體失敗就不進行下面的賦值。而operator =是可以保證異常安全的。
但是如果使用拷貝建構函式則不能保證上下文完整性。
高手們還有什麼其他的意見可以討論。
關於STL的個人看法
下面說的只是個人對stl的認識。不得不說,stl確實讓資料結構的運用變得很簡便。但我看來是有利有弊的。先說好處,經過stl封裝過的資料結構,使用起來更加方便快捷。很多次網路賽,用map,set可以很快解決一些農夫山泉題。用指標實現的鍊錶,佇列,棧等等,實現乙個功能要寫乙個函式,但stl中一句話就可以...
關於STL 的那些事
今晚參加訓練。樹狀陣列的練習,傻乎乎的用stl做了一晚,雖然題沒做出來,不過對stl的查詢有了更深一層的理解。關於stl。輸入輸出 vector push back pop back stack push pop queue push pop 頭 front 尾 back priority queu...
關於STL中的優先佇列
之前在c primer這本書上沒有看到關於優先佇列的東西,最近在看a 演算法中看到 總結一下 priority queue的用法 priority queue呼叫 stl裡面的 make heap pop heap push heap 演算法實現,也算是堆的另外一種形式。先寫乙個用 stl 裡面堆演...