0
template <class T>
class list
{
public:
    //stuff
    list(const list &cctorList); //cctor
private:
    struct node
    {
       node *next;
       node *previous;
       T *info;
    }

    node *firstNode; //pointer to the first node (NULL if none)
    node *lastNode; //pointer to the last node (NULL if none)
}

我现在正在尝试定义list(const list &cctorList); //cctor,但我遇到了麻烦。

这是我到目前为止所拥有的:

template <class T>
list<T>::list(const list &cctorList)
{
    node *another = new node;
    firstNode = another;
    another->previous = NULL;
    another->info = new T(*(cctorList->info));

    // ...
}

到目前为止一切都正确吗?有没有办法让我递归分配another->next?另外,有没有更简单的方法来使用迭代器来完成这个?

4

1 回答 1

2
  1. 你应该使用std::list. 实际上,您应该使用std::vector,因为对于大多数实际目的来说它更快(列表只有在对象非常大或构建起来非常昂贵时才会更快)并且您不需要随机访问。

  2. new T(*(cctorList->info));不会编译,因为cctorList( list&) 没有operator->并且它也没有info成员。

  3. 复制构造函数最好根据其他更原始的操作(如push_back迭代)来实现。所以首先做这些,然后复制构造函数变成:

    template <class T>
    list<T>::list(const list &cctorList)
    {
        std::copy(begin(cctorList), end(cctorList), std::back_inserter(this));
    }
    

    事实上,我只是模板该构造函数:

    template <class T, class Collection> list(const Collection &cctorList)
    

    (身体保持不变)。它用作复制构造函数,但也允许从任何其他可以隐式转换为 T 的任何类型的集合进行复制。

  4. 实际数据应按保存。即node应该定义为

    struct node
    {
        node *next;
        node *previous;
        T info;
    }
    

    无论如何,您都在复制该值,因此您无需针对何时进行两次单独的分配node以及T何时进行分配。


编辑:你说你想学习概念。但现代 C++ 最重要的概念是算法的组合。他们的定义通常是微不足道的。的基本实现std::copy只是:

template <typename InputIterator, typename OutputIterator>
OutputIterator copy(InputIterator begin, InputIterator end, OutputIterator out) {
    for(;begin != end; ++out, ++begin) *out = *begin;
}

现在这似乎没有分配任何东西。诀窍在于back_insertion_iterator. 插入迭代器是一种无需预先分配序列即可使其工作的技巧。它在基础集合上定义operator*using并忽略。这满足了“输出迭代器”的概念,因为它只保证在这两个调用严格交错时工作,并使算法可以处理从普通旧数组到输出流的许多事情。push_backoperator++

另一部分是虽然琐碎的定义是正确的,但它们不是库中使用的实际定义。库中的实际定义进行了优化。例如,通常std::copy会检查输入迭代器是否知道它们的距离,以及输出是否是插入操作符以对操作进行排序reserve并调用它以避免某些分配。这些是优化,取决于标准库的实现细节。

如果您想了解它们,您可以从标准库中写下事物的基本实现并测试它们的工作方式。std::copy但是您应该遵循标准库定义事物的方式,通过简单的辅助位(如、std::swap、插入迭代器适配器等)构建它们。如果你查看标准库,大多数函数都是单行的!

Edit2:尽管标准库提供了所有通用性,但仍然有人批评它不够通用。例如GotW #84: Monoliths “Unstrung”讨论了哪些方法std::string可以转换为通用算法。

于 2012-12-03T08:07:18.627 回答