-1

저는 C++을 처음 접했습니다. 나는 C++에서의 Singly Linked List의 장난감 구현을했습니다.C++의 List 클래스에 대한 소멸자

template<typename T> 
class List { 
    template<typename U> 
    struct Node { 
     U data_; 
     Node<U>* next_; 

     Node() : data_(0), next_(nullptr) {} 
     Node(U data) : data_(data), next_(nullptr) {} 
    }; 

private: 
    Node<T>* head_; 
    std::size_t size_; 

public: 
    List() : head_{nullptr}, size_{0} {} 

    void insert(const T& item) { 
     Node<T>* p(new Node<T>(item)); 
     if (size_ == 0) { 
      head_ = p; 
     } else { 
      p->next_ = head_; 
      head_ = p; 
     } 
     size_++; 
    } 
    std::size_t getSize() { 
     return size_; 
    } 

    ~List(){ 
    while(head_){ 
     Node<T> p = head_; 
     delete(p); 
     head_ = head_->next_; 
    } 
}; 

이 코드가 작동하는 것 같습니다. 그러나 문제는 new에 의해 할당 된 객체가 ~List() 소멸자에도 불구하고 결코 정리되지 않는다는 것입니다. 누군가가 나를 이해하는 데 도움이 될 수 있습니다, 어떻게 할당 된 노드를 정리하는이 클래스의 소멸자를 작성할 수 있습니까?

중요한 설명 : 스마트 포인터를 사용하여이 작업을 수행 할 수 있다는 것을 알고 있지만 이전 학교에서 힙을 관리하는 방법을 알고 싶습니다.

+0

은 당신이 그것으로 발생하는 문제에 대한 질문을 한 후 소멸자를 작성 시도하고 : 당신은 당신이 다음을 수행 할 수있는 요소를 나타 경우를 들어

당신. –

+0

'T '클래스의 소멸자는'~ T'라는 인자가없는 멤버 함수입니다. –

+1

목록의 노드를 반복하는 방법을 알고 있습니까? 그럼 당신은 기본적으로 당신이 알아야 할 모든 것을 알고 있습니다. –

답변

7
while(head_){ 
    Node<T> p = head_; <-- change to pointer 
    delete(p); <-- you can't delete this right now 
    head_ = head_->next_; 
} 

p은 포인터 여야합니다. 바로 p을 삭제할 수 없습니다. next 노드를 찾아 나중에 p을 삭제해야합니다. 또한 다음과 같이 delete p; 대신 delete (p);를 사용

~List() { 
    while(head_) { 
     Node<T> *p = head_; 
     head_ = head_->next_; 
     delete p; 
    } 
} 

의견에서 언급 한 바와 같이, Node 템플릿 일 필요는 없습니다. 수업을 단순화 할 수 있습니다. insert 또한 head_nullptr으로 초기화되기 때문에, 안전하게 일반적인 아이디어는 당신이 그것을 삭제해야 누가 결정하는 개체의 소유자 누구인지 파악해야한다는 것입니다 p->next_ = head_;

template<typename T> class List { 
    struct Node { 
     T data_; 
     Node* next_; 
     Node() : data_(0), next_(nullptr) {} 
     Node(T data) : data_(data), next_(nullptr) {} 
    }; 
    Node* head_; 
    std::size_t size_; 
public: 
    List() : head_{ nullptr }, size_{ 0 } {} 

    void insert(const T& item) { 
     Node* p = new Node(item); 
     p->next_ = head_; 
     head_ = p; 
     size_++; 
    } 

    std::size_t getSize() { 
     return size_; 
    } 

    ~List() { 
     while(head_) { 
      Node *marked = head_; 
      head_ = head_->next_; 
      delete marked; 
     } 
    } 
}; 
-1

할당 할 수 있습니다 단순화 할 수있다.

노드와 관련하여 List는 소유자입니다. 따라서 List가 객체의 소유권을 잃어 버리면 객체가 삭제되거나 소유권이 넘겨지는 방식으로 신중하게 모든 메소드를 개발해야합니다.

확실한 장소는 메모리를 비우는 것입니다. 먼저 목록을 삭제하십시오. 둘째, 요소를 제거 할 때 예를 들어 팝핑합니다.

두 경우 모두 살펴 봅니다.

먼저 목록을 삭제하십시오. 이를 위해 소멸자를 작성해야합니다. 소멸자는 목록을 반복하고 요소를 하나씩 삭제합니다. 이를 위해 @ barmak-shemiani의 대답을 참조하십시오. - 아무도 그것을 쓰려고하지

T pop() { 
    Node<T> *tmp = head_; 
    if (head_ != nullptr) 
     head_ = head_->next_; 
    T data = tmp->data_; 
    delete tmp; 
    return data; 
    } 
+2

게시 한 코드는 컴파일되지 않으며 버그가 있습니다. – Angew

+0

@Angew 무엇에 관한 버그? – mcsim

+0

호출시'head_'가 null 일 때 무엇을 반환합니까? 당신이 그것을 기대하지 않거나, 어떤 경우에는 무의미한가, 아니면 그렇게 될 것이라고 기대할 수 있습니다. 어떤 경우에는 그것을 완전히 처리해야합니다. – Angew