2008-12-14 67 views
6

我需要爲我的程序使用列表,並需要決定是否使用std :: vector或std :: list。 矢量的問題是沒有刪除方法和列表中沒有運算符[]。所以我決定寫我自己的擴展std :: list類並重載[]運算符。擴展std :: list

我的代碼如下所示:

#include <list> 

template <class T > 
class myList : public std::list<T> 
{ 
public: 
T operator[](int index); 
T operator[](int & index); 
myList(void); 
~myList(void); 
}; 

#include "myList.h" 

template<class T> 
myList<T>::myList(void): std::list<T>() {} 

template<class T> 
myList<T>::~myList(void) 
{ 
std::list<T>::~list(); 
} 

template<class T> 
T myList<T>::operator[](int index) { 
int count = 0; 
std::list<T>::iterator itr = this->begin(); 
while(count != index)itr++; 
return *itr;  
} 

template<class T> 
T myList<T>::operator[](int & index) { 
int count = 0; 
std::list<T>::iterator itr = this->begin(); 
while(count != index)itr++; 
return *itr; 
} 

我可以編譯它,但我得到一個鏈接錯誤,如果我嘗試使用它。有任何想法嗎?

+0

你`T運營商[](INT指數);`和`T運營商[](INT及指標);`但是你可能而是使用`T&operator [](int index)`和`const T&operator [](int index)const`。另外,在這些函數內部,你可以'while(index - )`而不是創建一個新變量來跟蹤計數。 – Dennis 2013-08-13 22:17:42

回答

10

所有模板代碼都應放在頭文件中。這個填充修復鏈接問題(這是最簡單的方法)。 它發生的原因是編譯器將每個源(.cc)文件與其他文件分開編譯。另一方面,它需要知道它需要創建什麼代碼(即,模板中的T被什麼替代),除非程序員明確地告訴它,或者在模板中包含所有代碼,否則無法知道它實例化發生。即當編譯mylist.cc時,它對mylist用戶和需要創建的代碼一無所知。另一方面,如果編譯listuser.cc並且存在所有mylist代碼,編譯器將創建所需的mylist代碼。您可以在here或Stroustrup中閱讀更多。

您的代碼有問題,如果用戶請求否定或太大(超過列表中的元素數量)會出現什麼問題。我沒有看太多。

除此之外,我不知道如何ü打算使用它,但你的運營商[]是O(N)時間,這可能會很容易導致O(N * N)循環......

+1

「你的操作符[]是O(N)時間」 - 這正是它不包含在標準的`std :: list <>中的原因。 – 2008-12-14 17:29:49

6

向量有erase method可以刪除元素。這不夠嗎?

+0

它不像std :: list中的remove方法那麼容易使用 – 2008-12-14 11:38:12

+0

然後使用std :: remove代替? – 2008-12-14 12:42:48

+0

不知道。我會看看 – 2008-12-14 15:20:48

1

您必須將所有模板代碼移動到標題中。

21

鑑於你原來的問題陳述,

我需要使用我的程序列表,並需要決定是否使用std :: vector或std :: list。 vector的問題是沒有remove方法,並且列表中沒有operator []。

沒有必要創建自己的列表類(這不是一個明智的設計選擇,無論如何,因爲std::list沒有虛析構函數,這是一個強烈的跡象表明,它不打算用作基類)。

您仍然可以使用std::vectorstd::remove函數實現您想要的功能。如果vstd::vector<T>,然後刪除值value,可以簡單的寫:

#include <vector> 
#include <algorithm> 
T value = ...; // whatever 
v.erase(std::remove(v.begin(), v.end(), value), v.end()); 
1

明顯的東西已經詳細描述:

但是你選擇實現的方法?

  • 析構函數。
    • 不需要編譯器會爲你生成。
  • 的兩個不同版本的operator []是毫無意義的
    • 你也應該uisng的std ::目錄:: SIZE_TYPE作爲索引
    • 除非你打算支持負的索引。
  • 有運營商沒有const的版本[]
  • 如果你要實現[]你也應該做的()
  • 你錯過了構建一個列表的所有不同的方式。
  • 容器應定義幾種類型的內部
5

除了其他很好的意見,延長一個標準集裝箱的最佳方式是不是推導,但寫自由的功能。例如,請參閱Boost String Algorithms如何用於擴展std::string和其他字符串類。

0

沒有必要調用std :: list的析構函數,因爲當自動調用myList的析構函數時,您已經從std :: list派生std :: list析構函數。

52

根據您的需要,您應該使用std::vector(如果您經常需要在最後添加/刪除以及隨機訪問)或std::deque(如果您需要經常在末尾或開始處追加/刪除,並且您的數據集非常龐大,仍然需要隨機訪問)。這裏是你展示如何作出決定,一個好的圖片:

Container Choice http://adrinael.net/containerchoice.png