对链接列表感到困惑

时间:2015-03-19 02:14:44

标签: c++ compiler-errors linked-list

template <class T>
class Node
{
public:
 T m_data;                  // Data to be stored
 Node<T>* m_next;     // Pointer to the next element in the list


 // Purpose: Default constructor
 // Postconditions: next pointer set to NULL
 // ---INLINE---
 Node() : m_next(NULL) {}

 // Purpose: Auxiliaty constructor, construct from parameters
 // Postconditions: data and next pointer set to parameters
 // ---INLINE---
 Node(const T& x, Node<T>* p)
         : m_data(x), m_next(p) {}

};

template <class T>
class LinkedList
{

public:

 Node<T>* head;     // Pointer to the head of the list

// Purpose: Default constructor
// Postconditions: head pointer set to NULL
// ---INLINE---
LinkedList() : head(NULL) {}





template<class T>
const LinkedList<T>& LinkedList<T>::operator =(const LinkedList<T>& rhs)
{
    if(this != &rhs)
    {
      if(head != NULL)
      {
        clear();
      }
      head = NULL;
      Node<T>* rhsptr = rhs.head;
      Node<T>* copyptr = new Node<T>;
      copyptr->m_data = rhs->m_data;
      while(rhs->m_next != NULL)
      {
       rhsptr = rhsptr->m_next;
       copyptr = new Node<T>;
       copyptr = copyptr->m_next;
       copyptr->m_data = rhsptr->m_data;
      }
      copyptr->m_next = NULL;

     }
     return(*this);

}

COPY OPERATOR

template<class T>
LinkedList<T>::LinkedList(const LinkedList<T>& rhs)
{

    *this = rhs;
}

当我编译时,它说:

  

linkedlist.hpp:24:25:错误:' - &gt;'的基本操作数有非指针类型'const

     

链表”

     

copyptr-&gt; m_data = rhs-&gt; m_data;                            ^   linkedlist.hpp:25:13:错误:' - &gt;'的基本操作数有非指针类型'const

     

链表”

     

while(rhs-> m_next!= NULL)

我很困惑因为我将rhsptr声明为指针类型所以我应该可以使用 - &gt;正确?

另外,如果这种编码一般起作用,我很困惑。我们已经在课堂上教过复制操作符应该模仿初始化并调用=运算符,但我看到一些代码正好相反。它们的复制构造函数被编码,赋值操作符调用它。

编辑2:这段代码给出了段错误,但我看不到任何东西。对此方面的任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:0)

您的声明或 rhs (对于复制构造函数是正确的)将其声明为引用,因此,而不是&#34; - &gt;&#34;你应该使用一个简单的&#34;。&#34;你在哪里得到错误。

使用&#34;&amp;&#34;在函数的参数中,它在语义上不同于它作为解除引用运算符的使用(&#34; 操作地址&#34;),尽管在功能上,它们的行为方式大致相同:它们阻止编译器在调用函数时制作对象的副本。以下是每种呼叫类型的示例:

    /* This requires a copy of the node for use by the function 
     * The copy is placed on the top of the stack, and ceases to exist
     * once the function exits.
     * The copy is made via your copy constructor */ 
    void fooA(Node<int> N){}


    /* This requires a copy of a pointer to your node. To access members,
     * you use the -> operator */
    void fooB(Node<int> * N){}

    /* This implicitly requires a copy of a pointer to your node, but this
     * happens without you manually doing a dereference */
    void fooC(Node<int> &N){}

    // Here we exemplify the call format
    int main(void){
        Node<int> N;
        fooA(N);
        fooB(&N);
        fooC(N);
        return 0;
    }

(请注意,我只使用Node作为示例,c ++中所有类型都是这种情况)

实际上创建了引用的呼叫(你的&#34; &amp; rhs &#34;)以允许更简单的sintax(使用&#34;。&#34;调用函数,而不需要调用函数中的&#34;&amp;&#34;而不是指针语义(例如:&#34; * rhs&#34;)。

至于你的第二个问题,你可以实现operator =作为对拷贝构造函数的调用,反之亦然,或者独立地,虽然根据我的经验(和个人偏好),编写代码更典型作为复制构造函数,然后从您的运算符实现引用它。

编辑:我应该补充一点,如果它不清楚,那么做一个对象的副本通常比使用指针(或引用)更加昂贵 - 指针通常会大约为4或8个字节(32对64位系统),但即使是简单的对象也可以大得多(节点应该是8或16个字节,例如,不计算运行复制构造函数所花费的时间)。

答案 1 :(得分:0)

针对“编辑2”问题。这些代码行:

   copyptr = new Node<T>;
   copyptr = copyptr->m_next;

将创建m_next值为NULL的新节点,然后将copyptr设置为该值。这导致copyptrNULL,当您尝试使用它时会导致错误。

相反,您希望更新当前copyptr的{​​{1}}值以指向新节点,然后将m_next设置为该新节点。

对代码稍作修改应该这样做:

copyptr