2014-04-18 1 views
0

쇼핑 목록을 저장할 단일 링크 된 목록이 포함 된 프로그램을 작성하고 있습니다. 각 노드에는 항목 이름, 수량 및 수량 설명 (예 : 달걀의 경우 12 개)이 있습니다. 모든 것은 소멸자를 제외하고 프로그램에서 찾아냅니다. 나는 그것이 무엇이 잘못되었는지 찾아내는 것처럼 보이지 않는다. 프로젝트 14 0x0FC7A9E8 (msvcr120d.dll)에Big Three를 올바르게 구현하는 방법 : 단독 링크 된 목록 (C++)

"처리되지 않은 예외 : 코드 다음 소멸자 호출 return 0;되고 메시지와 광고 delete current; 멈 여기서

드라이버 끝까지 실행한다. exe : 0xC0000005 : 액세스 위반 읽기 위치 0xFEEEFEE2. ".

아래의 세 가지 기능에 대한 구현을 게시했습니다. 기본 생성자는 두 포인터 (first, last)를 null으로, nodeCount0으로 초기화합니다.

문제를 찾을 수 없습니다. 어떤 도움이 필요합니까?

List::List(const List& b) 
{ 
    Node* newNodePtr = new Node; 
    Node* nodeCopy = b.first; 
    newNodePtr = nodeCopy; 
    first = newNodePtr; 
    last = newNodePtr; 
    nodeCount++; 
    nodeCopy = nodeCopy->getNext(); 
    while (last != b.last) 
    { 
     Node* newNode = new Node; 
     newNode = nodeCopy; 
     Node* currentNode = last; 
     currentNode->setNext(newNode); 
     last = newNode; 
     nodeCount++; 
     nodeCopy = nodeCopy->getNext(); 
    } 
} 

List::~List() 
{ 
    Node* current = first; 
    while (current != nullptr) 
    { 
     Node* _next = current->getNext(); 
     delete current; 
     current = _next; 
    } 
    first = nullptr; 
    last = nullptr; 
} 

List& List::operator=(const List& rho) 
{ 
    Node* current = first; 
    while (current != nullptr) 
    { 
     Node* _next = current->getNext(); 
     delete current; 
     current = _next; 
    } 
    first = nullptr; 
    last = nullptr; 

    Node* newNodePtr = new Node; 
    Node* nodeCopy = rho.first; 
    newNodePtr = nodeCopy; 
    first = newNodePtr; 
    last = newNodePtr; 
    nodeCount++; 
    nodeCopy = nodeCopy->getNext(); 
    while (last != rho.last) 
    { 
     Node* newNode = new Node; 
     newNode = nodeCopy; 
     Node* currentNode = last; 
     currentNode->setNext(newNode); 
     last = newNode; 
     nodeCount++; 
     nodeCopy = nodeCopy->getNext(); 
    } 
    return *this; 
} 

편집 : 기록 된대로 나는 또한 내와 push_back 기능을 추가했습니다 :

void List::push_back(Node* newNode) 
{ 
if (first == nullptr) 
{ 
    first = newNode; 
    last = newNode; 
} 
else 
{ 
    Node* currentNode = last; 
    currentNode->setNext(newNode); 
    last = newNode; 
} 
nodeCount++; 
} 

좋아 내가 아웃 냈어요 생각합니다. 이 코드는 작동하는 것 같고 내 교수가 제공하는 드라이버에 맞습니다.

List::List(const List& b) 
{ 
    this->copyList(b); 
} 

List::~List() 
{ 
    this->clearList(); 
} 

List& List::operator=(const List& rho) 
{ 
    this->clearList(); 
    this->copyList(rho); 
    return *this; 
} 

void List::clearList() 
{ 
    Node* current = first; 
    while (current != nullptr) 
    { 
     current = pop_front(); 
     delete current; 
     current = first; 
    } 
    first = nullptr; 
    last = nullptr; 
} 

void List::copyList(const List& b) 
{ 
    first = nullptr; 
    last = nullptr; 
    nodeCount = 0; 
    Node *headNode = b.getFirst(); 
    while (headNode != nullptr) 
    { 
     string des = headNode->getDescription(); 
     string qNa = headNode->getQuantityName(); 
     int qNu = headNode->getQuantityNumber(); 
     Node* newNode = new Node(qNu, qNa, des); 
     push_back(newNode); 
     headNode = headNode->getNext(); 
    } 
} 

Node* List::pop_front() 
{ 
    Node* saveFirst = first; 
    first = first->getNext(); 
    nodeCount--; 
    return saveFirst; 
} 

void List::push_back(Node* newNode) 
{ 
    if (nodeCount == 0) 
    { 
     first = newNode; 
     last = newNode; 
    } 
    else 
    { 
     Node* currentNode = last; 
     currentNode->setNext(newNode); 
     last = newNode; 
    } 
    nodeCount++; 
} 
+0

'노드'의 소멸자는 어떻습니까? 그걸 보여 주시겠습니까? – 0x499602D2

+0

저는 교수님이 Node 클래스의 소멸자를 포함하지 말라고 들었습니다. – JamaicanBambi

+0

이 코드는 안전하지 못하고 믿을 수 없을만큼 예외적이며 끔찍하게 누출됩니다. 교수님이'std :: shared_ptr'도 사용하는 것을 금하셨습니까? – Mgetz

답변

0

정확한 문제는 해결되지 않을 수도 있지만 언급 한 기능이 있다면 복사 생성자에 대한 의사 코드는 다음과 같습니다.

List::List(const List& b) 
{ 
    Node *headNode = b.getHeadNode(); 
    while (headNode != NULL) 
    { 
     push_back(headNode->getDataFromNode()); 
     headNode = headNode->getNextNode(); 
    } 
} 

그래서 기본적으로 전체 복사 생성자가 있습니다. 기본적으로 목록의 첫 번째 노드에서 시작하여 해당 노드에서 데이터를 가져오고 push_back()을 호출하여 새 데이터를 추가합니다. push_back()은 노드를 만들고, 데이터를 추가 한 다음, 목록의 뒤쪽에 올바르게 배치하는 모든 까다로운 작업을 수행한다고 가정합니다.

이 구현이 얼마나 작고, 작고, 직관적인지주의하십시오. 연결된 목록의 복사본을 만들기 위해해야 ​​할 일은 목록이 비어 있는지 (새 개체의 경우) 먼저 확인하고 이전 목록의 항목을 새 목록에 계속 추가하는 것입니다. push_back()은 목록에 항목을 추가하기 때문에 (노드를 작성하고이를 최종 노드에 연결하는 모든 복잡함을가집니다), 우리는이를 복사하여 스마트하게 만듭니다.

복사 생성자와 함께 사용하려면 할당 연산자가 필요합니다. 예제에서 할당 연산자는 단순히 처리하기 전에 모든 노드를 제거하는 clear() (함수가있는 경우)를 호출하는 것입니다.

이 모든 작업을 수행하려면 push_back() 함수가 완벽하게 작동해야합니다. 비어 있지 않은 빈 목록의 끝에 삽입을 올바르게 처리하는 방법을 알아야합니다.

편집 : 드라이버 코드가와 push_back 전에 새 노드를 (그러므로와 push_back 새 노드를 할당하지 않습니다) 만들 않는 경우

, 다음 대체 코드를 사용할 수 있습니다 :

List::List(const List& b) 
{ 
    Node *headNode = b.getHeadNode(); 
    while (headNode != NULL) 
    { 
     Node *newNode = new Node(headNode->getDataFromNode()); 
     push_back(newNode); 
     headNode = headNode->getNextNode(); 
    } 
} 

에서 대체 버전, 새 노드의 생성자를 데이터로 인수로 생성 할 수 있다고 가정합니다. 나는 개인적으로 push_back()을 사용하는 디자인이 노드 생성의 모든 작업을 수행하는 것을 좋아하지 않지만 또 다른 문제이다.

+0

도움 주셔서 감사합니다! 나는 당신이 그것을 보는 것을 꺼려하지 않으면 포스트에 나의 고정 된 코드를 추가했다. 'push_back' 함수에 새로운 노드를 동적으로 할당하지 않은 유일한 이유는 드라이버가 이미 그것을했기 때문입니다. 그리고 우리는 제공된 드라이버를 변경하지 않아야합니다. 필자는'copyList' 함수에 새로운 노드를 할당하여이를 보완했습니다. 그러나이 프로젝트 밖에서 나는 당신이 말하는 것을보고 클래스 코드 내에서 노드를 생성해야합니다. – JamaicanBambi

+0

@ user3208991 - push_back()을 사용하는 현재 시나리오를 포함하도록 답변을 업데이트하여 목록 끝에 노드를 추가하십시오. – PaulMcKenzie

0

그것은 적어도 먼저 소멸자 호출 할 때를 가리키는 무엇에 부분적으로 의존한다 : 나는 큰 세 가지 기능과 그들이 전화를 다른 모든 기능을 포함 시켰습니다 아래.

코드가 노드의 내용을 복사하지 않습니다. 대신 포인터 만 조작하므로 dyp에서 지적했듯이 누수가 있습니다. Node * newNodePtr = new Node; 노드 * nodeCopy = b.first; newNodePtr = nodeCopy;

copy-swap 관용구를 읽고 싶을 수도 있습니다. What is the copy-and-swap idiom?