2010-06-08 74 views
0

爲什麼C++的向量類調用拷貝構造函數?爲什麼它不僅僅是對基礎數據進行memcpy?那不會很快,並且移除移動語義的一半需求嗎?在STL中使用memcpy

我無法想象這種情況會變得更糟,但是再一次,也許只是因爲我的想象力很不夠。

+0

你可能想看看這裏的一些評論,他們解釋了爲什麼不使用memcpy:http://bytes.com/topic/c/answers/861170-yet-another-thought-about-stl- vector – 2010-06-08 23:47:10

回答

13

因爲需要通知對象正在移動它。例如,可能會有指向該給定對象的指針,因爲該對象正在被複制,所以需要對其進行修復。或者引用計數智能指針的引用計數可能需要更新。或者....

如果你只是memcpy的底層內存,那麼你最終會調用析構函數兩次在同一個對象,這也是不好的。如果析構函數控制像操作系統文件句柄的東西呢?

編輯:總結上面: 複製構造函數和析構函數可以有副作用。這些副作用需要保留。

+0

析構函數如何被調用兩次? – 2010-06-08 23:48:58

+0

爲什麼引用計數需要更新?還有相同數量的參考文獻! – 2010-06-08 23:49:57

+2

你記錄了這個對象。現在有兩個副本。需要在兩者上調用析構函數。 – 2010-06-08 23:50:12

4

您可以安全地使用memcpy POD和內置類型。那些被定義爲沒有任何語義,除了是關於內存的一大堆比特之外。

但是,具有構造函數和析構函數的類型必須構造並銷燬以保持不變量。雖然您可能能夠創建可以memcpy和具有構造函數的類型,但在類型簽名中很難表達它。因此,不是可能違反與具有構造函數和/或析構函數的所有類型相關聯的不變量,而是在必要時通過使用複製構造函數來維持不變量的STL錯誤。

這就是爲什麼C++ 0x增加了通過右值引用移動語義的原因。這意味着STL容器可以利用提供移動構造函數的類型,併爲編譯器提供足夠的信息來優化其他昂貴的構造。

+0

請注意,當InputIter :: value_type與OutputIter :: value_type和POD相同時,'std :: copy '實際上可能會使用'std :: memcpy'。 – MSalters 2010-06-09 08:57:54

+0

@ MSalters:這不完全正確。一對'std :: list's可以滿足這些要求,你當然不能在那裏使用'memcpy'。它僅適用於'std :: vector'和'std :: basic_string' - 也就是說,需要其內容連續的容器。 – 2011-04-29 18:09:41