2008-12-14 68 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