2010-09-28 66 views
2

我目前正在爲鏈接列表類實現一個複製構造函數。當我使用另一個鏈接列表作爲參數創建類的新實例時,正在爲我作爲參數傳遞的對象調用構造函數。這讓我難以置信。下面是部分有必要了解這是怎麼回事的主要方法:在錯誤的對象上調用複製構造函數

int main() 
{ 
    LinkedList ll; 
    LinkedList ll2(ll); 
} 

所以,與其呼籲[112拷貝構造函數,用於LL拷貝構造函數被調用。在我試圖將ll複製到一個新的LinkedList中之前,我已經確認ll的大小是正確的3,即ll2。拷貝後,兩者的大小相同,大於3,但更奇怪的是,ll的拷貝構造函數被調用,而不是ll2的拷貝構造函數。由於我使用的是VC++,因此我已經通過該程序來確認這一點。

下面是LinkedList類的拷貝構造函數:

LinkedList::LinkedList(const LinkedList & other)   
{ 
    LLNode *otherCurNode = other.GetFirst(); 
    if (otherCurNode != NULL) 
    { 
     front = new LLNode(otherCurNode->GetValue(), NULL, NULL); 
     back = front; 
    } 
    else 
    { 
     front = NULL; 
     back = NULL; 
    } 
    LLNode *curNode = front; 
    while (otherCurNode != NULL) 
    { 
     Insert(otherCurNode->GetValue(), curNode); 
     curNode = curNode->GetNext(); 
     otherCurNode = otherCurNode->GetNext(); 
     back = curNode; 
    } 
    numNodes = other.GetSize(); 
} 

我的道歉,如果這最終是一個簡單的問題 - 我是相當新的C++。任何幫助將不勝感激!

+1

從你顯示的代碼中,第一行應該爲'll'調用一個拷貝,第二行爲'll2'。你如何確定哪個副本被調用?您是否可以將您的代碼縮減爲一個簡單的,自包含的代碼片段,該代碼片段展現您認爲您所看到的行爲?很可能,將代碼拷貝到這樣的代碼片段中,你會發現你的問題。如果不是的話,你有一段完美的代碼可以回到這裏,並詢問(一個新問題)。 – sbi 2010-09-28 05:37:27

+0

WOW。我遵循你的建議,並慢慢地將一些片段添加到一個非常基本的程序中來複制功能。然後,我再次回到我的程序上工作,Voila,問題消失了。由於我不記得修改任何代碼至少一個小時,所以我沒有想到我做了什麼,但是我要撤消一些最近的更改,以查看我是否無法弄清楚什麼是導致它... – AndyPerfect 2010-09-28 06:41:18

+0

所以我發現了什麼問題。我的結構如下:LinkedList.h包含類聲明,LinkedList.cpp包含類中包含的所有方法的實現。 TestCases.cpp包含LinkedList.h。但是,我在LinkedList.cpp中聲明瞭LinkedList的類變量,而不是我的頭文件。我可以在三個小時看完之後向你保證,我不會再犯這個錯誤了。再次感謝你們所有的答案!你的答案幫我搞定了全部數字=) – AndyPerfect 2010-09-28 06:48:23

回答

7
LinkedList ll = LinkedList(); 

這創建一個鏈表實例,然後這個實例被複制構造。這看起來像Java或C#主義。它實際上是等同於:

LinkedList ll(LinkedList()); 

要創建一個空的鏈表,簡單的寫:

LinkedList ll; 

這將隱式調用默認的構造函數。

此外,請確保您有一個默認的構造函數,將鏈表正確初始化爲空。如果你沒有一個,那麼這個列表的變量將以堆棧中的垃圾值結束。

+0

我想這是我的Java/VB/C#閃耀通過=)。我修復了我原來的代碼,但問題仍然存在。 – AndyPerfect 2010-09-28 03:55:44

+5

不,不要添加括號來顯式調用構造函數。對於不帶參數的構造函數,它將被解釋爲函數聲明。 – jamesdlin 2010-09-28 03:56:15

+0

@jamesdlin好點。我正要添加一個關於'typename'關鍵字的註釋,但是真的更好,我只是完全刪除了這個句子。 – 2010-09-28 03:58:54

2

奇怪的事情往往是不正確的內存處理的跡象。我可以看到您發佈的代碼的一個直接問題,其他功能中可能存在類似的問題。

就行while (otherCurNode->GetNext() != NULL),如果otherCurNode已經是NULL,就會發生壞事。當另一個列表爲空時以及在通過otherCurNode = otherCurNode->GetNext();到達列表末尾時都是如此。你真的想要它while (otherCurNode != NULL)

+0

可以理解。我認識到這是一個問題,但實際上並沒有解決手頭真正的問題,因爲錯誤對象的構造函數被調用。感謝您的提示,雖然=) – AndyPerfect 2010-09-28 04:09:14

1

因此,不是調用ll2的複製構造函數,而是調用ll的複製構造函數,並將ll2設置爲與ll相同的引用。

您可以確定這不是發生了什麼事。您的llll2變量(順便說一句,您可以看到爲什麼在短名稱中使用小寫字母l從來不是一個好主意)分配在堆棧上,它們不是引用。要查看此信息,請在兩個變量都在範圍內時打開快速監視,然後鍵入&ll,然後輸入&ll2。你會看到他們有不同的地址。

你的默認構造函數和賦值運算符是什麼樣的?還有其他的構造函數嗎?任何其他你指定front實例變量的地方?

+0

的確,我已檢查並確保ll和ll2位於內存中的不同位置。有趣的是,這兩個值都指向內存中的相同位置... 在行LinkedList ll2(ll)期間修改了ll的front的位置;這整個情況讓我感到困惑。 – AndyPerfect 2010-09-28 04:32:55

+0

看起來您已將您的賦值運算符作爲默認值,該值由編譯器自動生成。它分配所有成員,包括'front'。這不是你想要的行爲。 – 2010-09-28 05:35:38

+0

規則是,如果你實現自定義拷貝構造函數,那麼也要實現賦值操作符。 – 2010-09-28 05:36:15