條款8 不要把auto ptr放入容器

2021-04-08 14:53:32 字數 2717 閱讀 6034

本來沒有打算自己翻譯effective stl的,怕影響大家情緒:),只是發現有些條款在網路上找不到,只好自己翻譯了。--winter

坦白的講,這個條款不應加入本書,因為包含atuo_ptr的容器(coaps)本來在stl中就是禁止的。就算你這麼用了,編譯器也不會編譯你的**。而標準委員會也沒有解釋為什麼不能這樣。對於coaps我應該什麼都不用說的,因為你的編譯器應該替你做好了一切工作,所有這種類似的**都不應該被編譯。

可惜的是,許多程式設計師使用的stl版本並不拒絕coaps,更要命的是,許多程式設計師發現這個曾經非常簡單直接用於減少記憶體洩漏的自動指標經常伴隨指標容器。因此雖然stl可能並不支援,許多程式設計師還是去試圖使用coaps。

我來講解coaps到底有什麼缺點,以至於標準委員會都明確禁止它。好了,馬上開始。我講乙個不足點,不用auto_ptr的相關知識,甚至不用任何stl容器的知識你都能明白:coaps不靈活(portable)。他們到底能怎樣?c++標準中就禁止它了,好一點的stl平台將都不容許它的存在,這些都是有原因的,我會慢慢告訴你。當前的stl平台沒有禁止coaps,你會發現存在coaps時,**比以前更加不靈活了。只要你很看中靈活性(當然應該如此),你就應該拒絕使用coaps。

但是可能你並不關心靈活性,如果真是這樣,請允許我友善的提醒你,就是拷貝atuo_ptr的獨特的(也可以說成是奇怪的)定義。

當你拷貝乙個auto_ptr,被auto_ptr所指的物件的所有權已經轉移到了新的auto_ptr中去了,原有的auto_ptr被設定為null。你理解的沒有錯:拷貝乙個auto_ptr,將會改變auto_ptr本身的值。

auto_ptrpw1 (new widget); // pwl1points to a widget

auto_ptrpw2(pw1); // pw2 points to pw1's widget;

// pw1 is set to null. (ownership

// of the widget is transferred

//from pw1 to pw2.)

pw1 = pw2; // pw1 now points to the widget

// again; pw2 is set to null

bool widgetapcompare(const auto_ptr& lhs,

const auto_ptr& rhs) // operator< exists for widgets

vector> widgets; // create a vector and then fill it

//with auto_ptrs to widgets;

// remember that this should

//不管這些**看起來有多麼合理,這個執行結果肯定是不合理的。最簡單的,排序的時候,widgets中會有乙個或者多個auto_ptrs的值被改為null。vector本身的排序操作,卻改變了容器本身的值。把這其中的原理弄明白還是比較值得的,我們來推斷一下:

它可能是因為sort演算法的實現(乙個公用的方法,並被證明過的),在快速排序演算法過程中不得不使用一些臨時變數。我們並不關心快速排序演算法的具體實現,但其基本概念是,排序乙個容器中的元素,必定會有某個元素用來作為「pivot element」,然會遞迴比較乙個元素比這個pivot element大於小於或等於進行排序。在排序內部,實現方法可能像這樣:

not

compile!

sort(widgets.begin(), widgets.end(), // sort the vector

widgetapcompare);

template// this declaration for

class compare> // sort is copied straight

void sort( randomaccesslterator first, // out of the standard

randomaccesslterator last,

compare comp)

elementtype pivotvalue(*i);

因為它從被排序的範圍中拷貝了乙個元素到本地的臨時物件中,在我們的討論中,這個元素是乙個自動指標auto_ptr,所以這個動作讓被拷貝的那個auto_ptr的值變成了null,也就是在vector中的元素的值變成了null,而且當結束pivotvalue的定義域時,它又自動刪除了它指向的widget。如果此時讓sort函式直接返回,vector容器的值已經發生了變化,至少又乙個widget的值被釋放了。由於快速排序是乙個遞迴演算法,每次遞迴都會選擇pivot element,因此將會又好幾個vector的元素被設定為null,同時會有好幾個widget物件被釋放。

這是乙個非常骯髒的陷阱,這也是為什麼標準委員會如此努力的工作以避免你不會掉入這個陷阱中。為了尊重他們的工作,也為了你自己的利益,絕不要把auto_ptrs放入你的容器,甚至當你的stl平台允許你這麼做,你也不要這麼做。

如果你的目標是用乙個包含**art pointer(智慧型指標)的容器,你還是幸運的。包含**art pointers的容易都可以很好的工作。條款50,描述了在哪兒你能找到和stl容器結合十分完美的**art pointer。只是你不應該把auto_ptr放入容器,而不是**art pointer!  

這可能很有趣,但當然是不正常的,你作為乙個stl的使用者,要你小心使用的原因是,auto_ptr會導致一些莫名其妙的結果。舉例來說,詳細看看下面看似「清白無辜」的**,這些**先產生乙個包含atuo_ptr的vector,然後通過比較指向widgets的指標來對vector進行排序:

不要把領導當成客戶

以客戶為中心的思想,幾乎在所有公司都會被提及和執行。他的終極目標是和客戶達成共贏。但是,並不是所有人都理解了以客戶為中心。我今天想說的是 於我們的一次工作討論。幾位新同事在分享服務案例的時候,提到自己的客戶,經常把經理當成客戶。他們是這樣理解的,經理把工作交給他們,經理在給他們分配工作的同時,也給他...

不要把大腦當做磁碟

不要把大腦當做磁碟 上學的時候我們會傾向於 被迫 背很多東西,畢業後發現大部分都又還給了老師。但是受過教育和沒有受過教育的人還是有區別的,差別可能就在於剩下的那一小部分。工作後,在工作中可能還會傾向於去記憶很多東西,但是我發現很多時候是沒有必要的,而且有時候甚至會成為一種負擔。第乙個原因是之前被我們...

不要把愛底線放低

我們一直覺得妥協一些 將就一些 容忍一些可以得到幸福,但當你的底線放得越低,你得到的就是更低的結果。不要總抱怨自己遇到的男人都不靠譜,如果別人總這麼對你,那麼一定是你教會了別人用這樣的方式對你。我們應該相信愛是平等的,可以付出更多,也可以愛他更多,幸福會更多。一 假如你想要一件東西,就放它走。它若能...