2011-06-14 34 views
2

我有以下問題:如何標準::矢量對象複製到其內部存儲

void add(){ 
    cRow Row(); 
    Row.add("Column", "Value"); 
    std::vector<cRow> mRows; 
    mRows.push_back(Row); 
} 

cRow::cRow(): mCol(NULL), mVal(NULL) { 
} 

cRow::add(const char* Col, const char* Val){ 
    mCol = strdup(Col); 
    mVal = strdup(Val); 
} 

cRow::~cRow(){ 
    free(mCol); 
    free(mVal); 
} 

加上局部變量行向量後,調用析構函數爲該行和琴絃被釋放。

顯然,向量中存儲行的字符串指針現在也被釋放。離開本地作用域後對行的任何訪問都將導致段錯誤。

行的轉儲照顧2個呼叫這樣的:

| (null) | (null) | 
----------------------------------------------------- 
| (null)| (null) | 
| LastContainerUpdatePropagation| 1307967498 | 
------------------------ END ------------------------ 

後3個電話:

| (null) | (null) | 
----------------------------------------------------- 
| (null)| (null) | 
| (null)| (null) | 
| LastSystemUpdatePropagation| 1307967498 | 
------------------------ END ------------------------ 

完全離開範圍而無需添加新行之後,每一行被釋放。

所以,現在我的問題:std:vector複製對象如何?我需要做些什麼來保持指向字符串的指針或將它們複製到另一個空間中?

非常感謝!

+1

'cRow Row()'沒有聲明變量,它聲明瞭一個函數。你發佈的代碼不是真實的,它甚至不會編譯。請發佈真實的代碼。 – AnT 2011-06-14 20:01:08

+0

兩個字:[規則三](http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)) – 2011-06-14 20:20:16

+0

這是三個字:) – bdonlan 2011-06-14 22:56:34

回答

9

std::vector使用copy constructor複製對象。由於您尚未定義複製構造函數,因此它將使用implicit C++ copy constructor,它只是遞歸地複製所有成員;這是不夠的,因爲你手動管理內存。

您需要定義自己的拷貝構造函數,或者使用類似std::string的東西,如果複製它將做正確的事情。

作爲一個良好的做法,任何具有非平凡析構函數的類都應該有一個拷貝構造函數和複製賦值運算符,正是出於這個原因(這被稱爲rule of three)。如果拷貝構造函數沒有意義(例如,對於像ostream這樣的內容),它應該是私有的,以防止意外複製。

+1

我會改變「非平凡類」爲「類與非平凡的構造函數「 - 類可以是很多不平凡的,仍然使用隱式複製構造函數。 – 2011-06-14 20:21:17

+1

「*作爲一個良好的做法,任何非平凡類應該有一個拷貝構造函數*」我完全不同意這個。絕大多數時候,隱式定義的拷貝構造函數將會很好(假設一個編寫C++而不是C-with-classes)並且編寫自己的編譯器只會引入錯誤的可能性。 – ildjarn 2011-06-14 20:21:41

+1

@ildjarn:沒錯。底層類(與原始類型接口的類)通常具有顯式拷貝構造函數等,但由它們構建的更高級別的類通常不需要任何明確定義的拷貝構造函數,儘管這些構造函數並不重要。 – AnT 2011-06-14 20:34:31

2

std::vector使用複製構造函數初始化其元素。如果你還沒有寫明確,編譯器提供了一個,但你正在做的內存管理,你需要:

  1. 提供一個拷貝構造函數,拷貝賦值操作符和析構函數(見Rule of Three
  2. 使用RAII並創建一個小封裝器來處理單個值的所有內存管理,並使用cRow類中所要求的那些(請注意,您仍然需要提供適當的拷貝構造函數,拷貝賦值操作符和析構函數爲你的RAII容器)。
  3. 使用爲您處理內存的類型,在您的示例中,您使用的是const char*,它可以用std::string替代,它將處理內存管理。

注:只有方法#3避免了必須編寫三個函數的自定義版本。