2014-09-27 29 views
0

對於這個程序,我創建了一個名爲Map的類,它通過存儲一個名爲MapItem的結構來像鏈接列表一樣工作。我注意到當我調用複製構造函數並傳入Map對象中沒有MapItems時,程序不會崩潰。但是,如果我調用copy-construct並將其中帶有MapItem的Map對象傳入,程序將崩潰。因此,我認爲問題可能在於我在下面附加的add函數,或者可能是我的析構函數,因爲當我註釋掉它的析構函數的時候它就起作用了。代碼粘貼在下面並保持儘可能最小。謝謝。當使用複製構造函數時,C++程序崩潰,動態內存可能是罪魁禍首?

Map.h

#include <iostream> 
using namespace std; 

template <class keyType, class valueType> 
struct MapItem 
{ 
    keyType key; 
    valueType value; 
    MapItem<keyType, valueType> *prev, *next; 
}; 

template <class keyType, class valueType> 
class Map 
{ 
    public: 
     Map(); // constructor for a new empty map 
     Map (const Map<keyType, valueType> & other); //constructor for a new map that is intialized with the values of other 
     ~Map(); // destructor 
     void add (const keyType &key, const valueType &value); 
      /* Adds a new association between the given key and the given value. 
      If the key already has an association, it should do nothing. 
      */ 
private: 
     /* The head and tail of the linked list you're using to store 
      all the associations. */ 
     MapItem <keyType, valueType> *head, *tail; 
     int sizeList; //size of the list 
     int position; //key-value pair we are looking at, can be from 1 - sizeList using next() and first() function 
}; 

Map.cpp

#include "Map.h" 

template <class keyType, class valueType> 
Map<keyType, valueType>::Map() 
{ 
    sizeList = 0; //set the size to 0 
    position = 1; //position is from 1 -> sizeList 
    head = NULL; //head points to NULL 
    tail = NULL; //tail points to NULL 
} 

template <class keyType, class valueType> 
Map<keyType, valueType>::Map(const Map<keyType, valueType> &other) //copy constructor 
{ 
    head = NULL; 
    tail = NULL; 
    sizeList = other.sizeList; //assign the same size (shallow copy) 
    position = other.position; //assign the same position (shallow copy) 
} 

template <class keyType, class valueType> 
Map<keyType, valueType>::~Map() 
{ 
    struct MapItem<keyType, valueType> *temp; //create temp variable to hold which item we are looking at in the list 
    temp = head; //start at the head 

    for(int i = 1; i <=sizeList; i++) 
    { 
     MapItem<keyType, valueType> *next = temp->next; 

     delete temp; //delete memory to pointed by temp 

     if(i != sizeList) //if we are not at the last node 
      temp = next; 
    } 
} 

template <class keyType, class valueType> 
void Map<keyType, valueType>::add(const keyType &key, const valueType &value) 
{ 
    struct MapItem<keyType, valueType> *newItem; //create pointer to new map item 

    if(sizeList == 0) //if linked list is empty, make newItem the HEAD 
    { 
     newItem = new MapItem<keyType, valueType>; //dynamically allocate a new item on the heap 
     newItem->key = key; //assign the key 
     newItem->value = value; //assign the value 

     sizeList++; //increment size 
     head = newItem; //set the HEAD of the list to newItem 
     tail = newItem; //set the TAIL of the list to newItem 
     newItem->prev = head; //previous item is the head (itself) 
     newItem->next = head; //next item is the head (itself) 
    } 
    else //if the linked list is not empty, add it in 
    { 
     struct MapItem<keyType, valueType> *temp = head; //store the first element in the linked list in temp variable 

     if(sizeList == 1) //if there is only one element in the list, check if they equal eachother 
     { 
      if(head->key != key) 
      { 
       newItem = new MapItem<keyType, valueType>; //dynamically allocate a new item on the heap 
       newItem->key = key; //assign the key 
       newItem->value = value; //assign the value 

       tail = newItem; //assign newItem as the TAIL     
       head->next = tail; //assign the next of HEAD to the new map item 
       head->prev = tail; //assign the previous of HEAD as the newItem (tail) 
       tail->prev = head; //assign head to PREV of newItem (tail) 
       tail->next = head; //assign HEAD to NEXT of newItem (tail) 
       sizeList++; //increment size of list 
      } 
     } 
     else 
     { 
      bool sameKey = false; //boolean value to check if the same key already exists, and if it does it will stop the loop 
      int i = 1; //which item we are looking at in the list 

      while(i <= sizeList && !sameKey) //while not past the end of the list, keep checking if a similar key exists 
      { 
       if(temp->key == key) 
        sameKey = true; 
       else 
       { 
        temp = temp->next; //go to the next map item 
        i++; 
       } 
      } 

      if(!sameKey) //if the same key has not been found 
      { 
       newItem = new MapItem<keyType, valueType>; //dynamically allocate a new item on the heap 
       newItem->key = key; //assign the key 
       newItem->value = value; //assign the value 

       tail->next = newItem; 
       newItem->prev = tail; 
       newItem->next = head; 
       tail = newItem; 
       head->prev = tail; 
       sizeList++; 
      } 
     } 
    } 
} 

TEST.CPP

#include "Map.cpp" 


int main() 
{ 
    Map<int, int> b; 
    b.add(1, 1); //if this line is commented out with the destructor intact, then the copy constructor call below works. if this line is NOT commented out with the destructor intact, the program crashes. 
    Map<int, int> a(b); 

    system("PAUSE"); 
    return 0; 
} 
+1

http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming) – NPE 2014-09-27 19:17:07

+0

我也有一個賦值操作符,因爲它沒有被使用,所以我只是沒有將它包含在這段代碼中。 – Tim 2014-09-27 19:21:59

回答

2

您的析構函數信任成員變量並嘗試刪除那麼多項。

但是,您的副本構造函數會使它們與數據量不一致,因爲它從不復制任何實際數據。

template <class keyType, class valueType> 
Map<keyType, valueType>::Map(const Map<keyType, valueType> &other) //copy constructor 
{ 
    head = NULL; // now there are zero items in the list 
    tail = NULL; 
    sizeList = other.sizeList; // this is a lie, really there are zero items 
    position = other.position; 
} 

當你拷貝一個空的列表,你sizeList組被意外正確的值,所以沒有什麼失敗。

0

ahead == NULL,所以當在析構函數你做

temp = head; //start at the head 
... 
MapItem<keyType, valueType> *next = temp->next; 

您正在訪問空指針。

+0

感謝您的回覆。我不相信這是答案,因爲析構函數中的for循環從i = 1開始,所以sizeList = 0時,for循環甚至不會執行。另外,如果我只是在test.cpp中沒有b.add(1,1)的地圖 b後跟Map a(b),程序將正常執行並且不會崩潰。謝謝你! – Tim 2014-09-27 19:49:47

+0

@Tem for destructior中的for循環具有條件'i <= sizeList'。 – 2014-09-27 19:51:38

+0

@Tim,如果你沒有添加任何東西,'sizeList == 0',並且循環不會執行,所以偶然一切正常。 – 2014-09-27 19:54:00

相關問題