2015-03-19 53 views
0
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); 

}困惑鏈表

拷貝操作符

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

    *this = rhs; 
} 

當我編譯,它說:

linkedlist.hpp:24:25: error: base operand of ‘->’ has non-pointer type ‘const

LinkedList’

copyptr->m_data = rhs->m_data; ^ linkedlist.hpp:25:13: error: base operand of ‘->’ has non-pointer type ‘const

LinkedList’

while(rhs->m_next != NULL)

我很困惑,因爲我宣佈rhsptr爲指針類型所以我應該可以使用 - >對嗎?

此外,我很困惑,如果這種編碼一般工作。我們已經在課堂上教過複製操作符應該模仿初始化並調用=操作符,但我已經看到一些代碼正好相反。他們的拷貝構造函數被編碼並且賦值操作符調用它。

編輯2:這段代碼給出了段錯誤,但我什麼也看不見。任何在這方面的幫助表示讚賞。

+2

'rhsptr'的確是一個指針,但'rhs'是一個參考,所以你必須使用點運算符,如'RHS。 m_data'。我想這就是你想寫的東西? – roeland 2015-03-19 02:26:23

回答

0

您的聲明或rhs(這對於拷貝構造函數是正確的)聲明它爲引用,因此,而不是「 - >」,您應該使用簡單的「。」。你在哪裏得到錯誤。

的使用中的功能的參數的「&」是從它的作爲引用操作(一個「地址的操作」),雖然在功能上,它們的行爲在大致相同的方式使用語義上不同:它們阻止編譯器在調用函數時創建對象的副本。以下是各呼叫類型的例子:

/* 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; 
    } 

(請注意,我只用節點爲例,這是對所有類型在C++而言)

呼叫引用(你的「& rhs「)實際上是爲了允許在指針函數中使用更簡單的sintax(在調用函數中使用」。「,而不需要調用函數中的」&「)而不是指針語義(例如:」* rhs「)。

至於你的第二個問題,你可以實現operator =作爲拷貝構造函數的調用,反之亦然,或者是獨立的,儘管根據我的經驗(和個人喜好),將代碼編寫爲副本更爲典型構造函數,然後從你的操作符實現中引用它。

編輯︰我應該補充說,萬一它不清楚,做一個對象的副本往往比使用指針(或引用)FAR更昂貴 - 指針將通常在4的順序或8個字節(32與64位系統),但即使是簡單的對象也可能更大(節點應該是8或16字節,例如,不計算運行拷貝構造函數所花費的時間)。

0

對於您的「編輯2」問題。這些代碼:

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

將創建一個新的節點與NULL一個m_next值然後設置copyptr爲該值。這導致copyptrNULL,當您嘗試使用它時會導致錯誤。

相反,您希望將當前的copyptrm_next值更新爲指向新節點,然後將copyptr設置爲該新節點。

到代碼中的微小變化應該這樣做:

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