扩展std :: list

时间:2008-12-14 11:30:16

标签: c++ templates list linker

我需要为我的程序使用列表,并且需要决定是否使用std :: vector或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;
}

我可以编译它,但如果我尝试使用它,我会收到链接器错误。有什么想法吗?

8 个答案:

答案 0 :(得分:53)

根据您的需要,您应该使用std::vector(如果您需要经常在最后添加/删除,并随机访问)或std::deque(如果您需要经常在最后添加/删除)或者在开始时,您的数据集很大,但仍然需要随机访问)。这是一张很好的图片,向您展示如何做出决定:

Container Choice
(来源:adrinael.net

答案 1 :(得分:21)

鉴于您原来的问题陈述,

  

我需要为我的程序使用列表,并且需要决定是否使用std :: vector或std :: list。向量的问题在于没有删除方法,并且列表中没有运算符[]。

没有必要创建自己的列表类(这不是一个明智的设计选择,因为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());

答案 2 :(得分:10)

所有模板代码都应放在头文件中。这个填充修复链接问题(这是最简单的方法)。 它发生的原因是因为编译器将每个源(.cc)文件与其他文件分开编译。另一方面,它需要知道它需要创建什么样的代码(即模板中的T被替换为什么),除非程序员明确地告诉它或者包含模板中的所有代码,否则没有其他方法可以知道它。实例化发生了。即当编译mylist.cc时,它对mylist用户一无所知,需要创建什么代码。另一方面,如果编译了listuser.cc,并且存在所有mylist代码,则编译器会创建所需的mylist代码。您可以在here或Stroustrup中阅读更多相关信息。

您的代码存在问题,如果用户请求为负数或太大(超过列表中的元素数量),该怎么办?而且我看起来并不太多。

此外,我不知道你打算如何使用它,但你的算子[]是O(N)时间,这可能很容易导致O(N * N)循环......

答案 3 :(得分:6)

向量具有可以删除元素的erase method。这还不够吗?

答案 4 :(得分:5)

除了其他优秀的注释之外,扩展标准容器的最佳方法不是通过派生,而是编写自由函数。例如,看看Boost String Algorithms如何用于扩展std::string和其他字符串类。

答案 5 :(得分:1)

您必须将所有模板代码移动到标题中。

答案 6 :(得分:1)

明显的内容已经详细描述:

但是你选择实施的方法是什么?

  • 析构。
    • 不需要编译器会为您生成。
  • operator []的两个不同版本毫无意义
    • 另外你应该将uisng std :: list :: size_type作为索引
    • 除非您打算支持负面指数。
  • 没有const版本的operator []
  • 如果您要实施[],您也应该在()
  • 进行
  • 您错过了构建列表的所有不同方法。
  • 容器应在内部定义多种类型

答案 7 :(得分:0)

没有必要调用std :: list的析构函数,因为当析构函数自动调用myList时,你已经从std :: list派生出std :: list析构函数。