【发布时间】:2014-06-03 11:52:10
【问题描述】:
我正在编写一个包含一个单链表来保存购物清单的程序。每个节点都有项目名称、数量和数量描述(即鸡蛋的打数)。除析构函数外,程序中的所有内容都可以找到。我似乎无法找到它有什么问题。
驱动程序将执行到代码为return 0; 的末尾,然后调用析构函数并在delete current; 行停止并显示以下消息:
“项目 14.exe 中
0x0FC7A9E8(msvcr120d.dll) 的未处理异常:0xC0000005:访问冲突读取位置0xFEEEFEE2。”。
我已经发布了下面三大功能的实现。默认构造函数将两个指针(first、last)初始化为null,将nodeCount 初始化为0。
我似乎找不到问题所在。有什么帮助吗?
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++;
}
【问题讨论】:
-
Node的析构函数呢?你能给我们看看吗? -
教授告诉我不要为 Node 类包含析构函数。
-
这段代码异常不安全,而且泄漏得非常厉害。你的教授也禁止你使用
std::shared_ptr吗? -
一个泄漏示例:
Node* newNodePtr = new Node; Node* nodeCopy = b.first; newNodePtr = nodeCopy;泄漏通过new分配的内存。 -
@Arun - 没错,我同意。许多拥有这些链表分配并实现复制构造函数的发布者都很难做到。他们没有看到他们正在编写的所有代码都已经在其他函数中完成了。如果他们没有编写这些其他函数,那么他们编写的链表有什么用,例如,如果您无法从中获取任何信息,或者无法向其中添加项目。
标签: c++ list memory-management linked-list destructor