2011-04-25 65 views
1

我喜歡在C++中實現鏈表,同時添加新節點I動態分配它,如果某些分配失敗,我想我的程序停止執行。在C++中動態分配鏈表。在防止內存泄漏的異常之後該怎麼辦?

「新節點」失敗後,拋出異常,所以我必須在異常處理程序中明確調用析構函數。 我該如何處理這種情況才能防止內存泄漏? 這裏是我的代碼,我已經寫了

LinkedList.h

#pragma once 
#include <iostream> 
#include <string.h> 
using namespace std; 

class LinkedList 
{ 
public: 
    class Iterator; 
private: 
    class Node 
    { 
     friend class Iterator; 
     friend class LinkedList; 
     char* m_word; 
     Node *m_next; 
     Node(const char* word,Node* next = NULL,Node* prev = NULL); 
     ~Node(); 
    }; 
    Node *m_head,*m_tail; 
    size_t m_num; 
public: 
    LinkedList():m_head(NULL),m_tail(NULL),m_num(0){}; 
    ~LinkedList(); 
    LinkedList& addFirst(const char* word); 
    LinkedList& addLast(const char* word); 
    Iterator erase(Iterator& it); 
    Iterator begin(); 
    Iterator end(); 
    Iterator find(const char* word); 
    size_t size()const{return m_num;}; 
    void print(); 

    friend class Iterator; 
    class Iterator 
    { 
     LinkedList& m_list; 
     Node *m_prev,*m_cur; 
     friend class LinkedList; 
     void next(); 
     void setLast(){m_cur = NULL,m_prev = m_list.m_tail;} 
    public: 
     Iterator(LinkedList& linkedList):m_list(linkedList),m_prev(NULL),m_cur(linkedList.m_head){} 
     Iterator& operator++(); 
     char* operator*(); 
     bool operator != (Iterator& it){return (m_cur != it.m_cur || m_prev != it.m_prev);} 
    }; 
}; 

LinkedList.cpp

#include "LinkedList.h" 


LinkedList::Node::Node(const char* word,LinkedList::Node* prev,LinkedList::Node *next) 
{ 
    char* tmpWord = new char[strlen(word)+1]; 
    strcpy(tmpWord,word); 
    m_word = tmpWord; 
    m_next = next; 
    if(prev != NULL) 
     prev->m_next = this; 
} 
LinkedList::Node::~Node() 
{ 
    delete[] m_word; 
} 

LinkedList::~LinkedList(void) 
{ 
    for(Iterator it = begin();it != end();) 
     erase(it); 
} 
LinkedList& LinkedList::addFirst(const char* word) 
{ 
    Node* node = new Node(word,NULL,m_head); 
    m_head = node; 
    if(m_tail == NULL) 
     m_tail = m_head; 
    ++m_num; 
    return *this; 
} 
LinkedList& LinkedList::addLast(const char*word) 
{ 
    if(m_head == NULL) 
     addFirst(word); 
    else 
    { 
     Node* node = new Node(word,m_tail,NULL); 
     m_tail = node; 
    } 
    ++m_num; 
    return *this; 
} 
LinkedList::Iterator LinkedList::begin() 
{ 
    Iterator it(*this); 
    return it; 
} 
LinkedList::Iterator LinkedList::end() 
{ 
    Iterator it(*this); 
    it.setLast(); 
    return it; 
} 
LinkedList::Iterator LinkedList::erase(LinkedList::Iterator& it) 
{ 
    if(it.m_cur != NULL) 
    { 
     Node* tmp = it.m_cur; 
     if(it.m_prev != NULL) 
      it.m_cur = it.m_prev->m_next = tmp->m_next; 
     else 
      it.m_cur = it.m_list.m_head = tmp->m_next; 
     if(tmp == it.m_list.m_tail) 
      it.m_list.m_tail = NULL; 
     delete tmp; 
     --m_num; 
    } 
    return it; 
} 
LinkedList::Iterator LinkedList::find(const char* word) 
{ 
    Iterator it = begin(); 
    for(;it != end();++it) 
    { 
     if(!strcmp(it.m_cur->m_word,word)) 
      break; 
    } 
    return it; 
} 

void LinkedList::Iterator::next() 
{ 
    if(m_cur != NULL) 
    { 
     m_prev = m_cur; 
     m_cur = m_cur->m_next; 
    } 
    else 
     m_prev = NULL; 
    return; 
} 
void LinkedList::print() 
{ 
    for(Iterator it = begin();it !=end();++it) 
     cout << it.m_cur->m_word; 
} 
LinkedList::Iterator& LinkedList::Iterator::operator ++() 
{ 
    next(); 
    return *this; 
} 
char* LinkedList::Iterator::operator *() 
{ 
    return m_cur->m_word; 
} 

//int main() 
//{ 
// LinkedList ll; 
// ll.addFirst("1"); 
// ll.addFirst("2"); 
// ll.addLast("3"); 
// ll.addLast("4"); 
// LinkedList::Iterator it = ll.find("5"); 
// return 0; 
//} 
+0

您再次發佈了您的問題?我想爲什麼我的答案沒有出現! :) – iammilind 2011-04-25 07:36:32

+0

請不要再提問相同的問題 - 它會分散那些本來會想到答案的人。 – sharptooth 2011-04-25 07:38:15

+1

如果你想存儲一個字符串,爲什麼不使用std :: string? – 2011-04-25 07:49:23

回答

2

「新節點」失敗後引發異常。

所以我必須在異常處理程序中明確調用析構函數。

不。如果構造函數沒有完成,那麼你不能調用析構函數(該對象從未被創建)。

我該如何處理這種情況才能防止內存泄漏?

如果在新的(std :: bad_alloc)中拋出異常,那麼你就不需要做任何事情。

如果從構造函數中引發異常。然後,每個完全構造的成員將自動調用它的析構函數。所以你不必擔心普通會員。如果你的任何成員都是指針(已經在構造函數中初始化),那麼你需要確保這些指針被刪除(這就是爲什麼你不想在你的對象中使用RAW指針(你需要智能指針))。

說出來。你不使用智能指針,但我看不到任何明顯的泄漏。

但是你擁有一個RAW類指針。你還沒有讀過關於3的規則(查看它)。目前,因爲你不遵守3的規則,所以下面的代碼會崩潰。

void myCode() 
{ 
    LinkedList list1; 
    list1.addFirst("Martin"); 

    LinkedList list2(list1); 
} 
2

如果new失敗,那麼你不必擔心內存泄漏,因爲你還沒有分配任何東西。如果需要,您可以只記錄該錯誤消息,並開始使用現有鏈接列表。

1

我沒有看到任何異常處理程序。 iammilind的答案是公平的,但即使你不想記錄失敗,你也必須編寫一個異常處理程序,因爲如果你不是,異常會進入更高的上下文,它可以用一個熟知的消息來停止你的程序你可以在調試器中看到:UNHANDLED EXTEPTION at .... 我懷疑你在術語內存泄漏的情況下。