【问题标题】:Copy constructor with vector with custom class not working?使用带有自定义类的向量复制构造函数不起作用?
【发布时间】:2014-07-03 11:51:28
【问题描述】:

我正在尝试通过 LinkedList 为冲突实现 Hashtable,但在 Hashtable 中实现复制构造函数时遇到问题(与 const 正确性的东西混淆)。

这是我看到的错误:

void LinkedList<KVP<T>>::add(const KVP<T> &)' : cannot convert argument 1 from 'const int' to 'const KVP<T> &

这是我的代码:

哈希表:

#include <stdlib.h>
#include <string>
#include <vector>
#include "LinkedList.h"
#pragma once

template <typename T>
struct KVP
{
    KVP() {}
    KVP(const T &data, const std::string &key) : data(data), key(key) {}
    const std::string key;
    T data;
};

template <typename T>
class Hashtable
{
    typedef KVP<T> kvp;
    typedef LinkedList<kvp> list;

    std::vector<list> table;
    std::size_t size;

public:

    Hashtable(int size) : size(size), table(size) {}
    Hashtable(const Hashtable& other) : size(other.size) 
    {
        table = other.table; //this causes problems
    }
    Hashtable& operator=(Hashtable other)
    {
        swap(*this, other);
        return *this;
    }
    ...  
};

链接列表:

#include <stdlib.h>
#include <memory>

#pragma once

template <typename T>
class LinkedList;

template <typename TNode>
class LinkedListIterator
{
    friend class LinkedList<typename TNode::value_type>;
    TNode* p;
public:
    LinkedListIterator(TNode* p) : p(p) {}
    LinkedListIterator(const LinkedListIterator& other) : p(other.p) {}
    LinkedListIterator& operator=(LinkedListIterator other) { std::swap(p, other.p); return *this; }
    void operator++() { p = p->next; }
    void operator++(int) { p = p->next; }
    bool operator==(const LinkedListIterator& other) { return p == other.p; }
    bool operator!=(const LinkedListIterator& other) { return !(p == other.p); }
    const int& operator*() const { return p->data; }
    LinkedListIterator<TNode> operator+(int i)
    {
        LinkedListIterator<TNode> iter = *this;
        while (i-- > 0 && iter.p)
        {
            ++iter;
        }
        return iter;
    }
};

template <typename T>
class Node
{
    friend class LinkedList<T>;
    friend class LinkedListIterator<Node<T>>;
    friend class LinkedListIterator<const Node<T>>;

    Node() : next(nullptr) {}
    Node(const T &data) : data(data), next(nullptr) {}
    Node<T> *next;
    T data;
public:
    typedef T value_type;
};

template <typename T>
class LinkedList
{
    typedef Node<T> node;

    std::size_t size;
    std::unique_ptr<node> head;
    std::unique_ptr<node> tail;

    void init()
    {
        size = 0;
        head.reset(new node);
        tail.reset(new node);
        head->next = tail.get();
    }

public:
    typedef LinkedListIterator<node> iterator;
    typedef LinkedListIterator<const node> const_iterator;

    LinkedList() { init(); }

    LinkedList(const LinkedList& other)
    {
        init();
        const_iterator i = other.begin();
        while (i != other.end())
        {
            add(*i);
            i++;
        }

        head.reset(other.head.get());
        tail.reset(other.tail.get());
    }

    LinkedList(LinkedList&& other)
    {
        size = other.size;
        head = other.head;
        tail = other.tail;
        other.size = 0;
    }

    LinkedList& operator=(LinkedList other)
    {
        swap(*this, other);
        return *this;
    }

    LinkedList& operator=(LinkedList&& other)
    {
        assert(this != &other);     
        while (head->next != tail)
            remove(begin());
        head = other.head;
        tail = other.tail;
        size = other.size;
        other.size = 0;
        return *this;
    }

    virtual ~LinkedList()
    {
        while (head->next != tail.get())
            remove(begin());
    }

    friend void swap(LinkedList& first, LinkedList& second)
    {
        std::swap(first.size, second.size);
        std::swap(first.head, second.head);
        std::swap(first.tail, second.tail);
    }

    void add(const T &value)
    {
        node *first = new node(value);
        first->next = head->next;
        head->next = first;
        size++;
    }

    void remove(iterator& removeIter)
    {
        node *last = head.get();
        iterator i = begin();

        while (i != removeIter)
        {
            last = i.p;
            ++i;
        }

        if (i != end())
        {
            last->next = i.p->next;
            size--;
            delete i.p;
        }
    }

    const int getSize() 
    { 
        return size;
    }

    iterator begin() 
    {
        return iterator(head->next);
    }

    const_iterator begin() const
    {
        return const_iterator(head->next);
    }

    iterator end()
    {
        return iterator(tail.get());
    }

    const_iterator end() const
    {
        return const_iterator(tail.get());
    }
};

在它自己的 LinkedList 复制 ctor 似乎可以工作,例如编译:

LinkedList<int> list;
LinkedList<int> list2;
list2 = list;

但这不是:

Hashtable<int> table1(50);
Hashtable<int> table2 = table1;

编辑:另外,如果我用指针定义表格:

std::vector<list*> table; 

它有效,但我认为这不是最好的方法。

【问题讨论】:

  • 您的const_iterator 是如何定义的?从错误中,它似乎在取消引用时返回int。这个错误可能会产生误导,但如果不知道它来自哪里,就很难说清楚。
  • 您需要为HashTable 定义赋值运算符:Hashtable&lt;int&gt; table2 = table1;
  • 如果你想使用拷贝构造函数进行这个操作,写成这样:Hashtable&lt;int&gt; table2(table1);.
  • @djikay 如果我调试,它实际上是在调用 copy ctor。哈希表 table2(table1);给出完全相同的错误。
  • 好的,如果你定义你的复制构造函数如下? Hashtable(const Hashtable&amp; other) : size(other.size), table(other.table) { }(抱歉,cmets 中的代码格式不太好)。

标签: c++ c++11 linked-list constants copy-constructor


【解决方案1】:

您的LinkedListIterator&lt;const Node&lt;T&gt;&gt;::operator* 返回const int&amp;,而不是LinkedList&lt;T&gt; 的值类型。您的LinkedList&lt;int&gt; 测试通过了,因为模板参数恰好与operator* 的硬编码返回类型匹配。

【讨论】:

  • 所以我添加了 typedef typename TNode::value_type T; const T& operator*() const { return p->data;并且看起来没有更多的编译错误。你发现这一点的方式令人印象深刻:)
  • @DaveS 实际上在我之前得到了它,甚至没有找到 const_iterator 的定义。
猜你喜欢
  • 2017-11-15
  • 2018-07-17
  • 1970-01-01
  • 2012-02-28
  • 2017-04-10
  • 1970-01-01
  • 1970-01-01
  • 2015-02-18
  • 1970-01-01
相关资源
最近更新 更多