C++设置对象属性时发生内存访问冲突
我的代码的一部分无法正常工作。构建一个基本的链表来学习指针。我想我已经掌握了大部分内容,但是任何使用我创建的函数(push_back)的尝试都会在设置指针值时引发内存访问错误。
不完全确定出了什么问题,因为使用push_front工作得很好,它的工作原理几乎完全相同。
有什么想法吗? =/
代码:
driver.cpp
#include <string>
#include <iostream>
#include "linklist.h"
#include "node.h"
using namespace std;
// printList function
// Purpose: Prints each node in a list
// Returns: None.
// Pre-Conditions: List must have member nodes.
// Post-Conditions: None.
void printList(linklist);
int main()
{
linklist grocery;
grocery.push_front(new node("milk", "1 gallon"));
grocery.push_front(new node("bread","2 loaves"));
grocery.push_front(new node("eggs","1 dozen"));
grocery.push_front(new node("bacon","1 package"));
cout << "First iteration:" << endl;
printList(grocery);
cout << "----------------------" << endl << endl;
grocery.push_front(new node("hamburger","2 pounds"));
grocery.push_front(new node("hamburger buns", "1 dozen"));
cout << "Second iteration:" << endl;
printList(grocery);
cout << "----------------------" << endl << endl;
node* deleteMe = grocery.pop_front();
delete deleteMe;
cout << "Third iteration:" << endl;
printList(grocery);
cout << "----------------------" << endl << endl;
grocery.push_back(new node("orange juice","2 cans"));
grocery.push_back(new node("swiss cheeese","1 pound"));
cout << "Fourth iteration:" << endl;
printList(grocery);
cout << "----------------------" << endl << endl;
deleteMe = grocery.pop_back();
delete deleteMe;
cout << "Fifth iteration:" << endl;
printList(grocery);
cout << "----------------------" << endl << endl;
while (grocery.getNodeCount() != 0)
{
deleteMe = grocery.pop_front();
cout << "Cleaning: " << deleteMe->getDescription() << endl;
delete deleteMe;
}
system("PAUSE");
return 0;
}
void printList(linklist input)
{
node* temp = input.getFirst();
for (int i = 0; i < (input.getNodeCount()); i++)
{
cout << temp->getQuantity() << " " << temp->getDescription() << endl;
temp = temp->getNextNode();
}
}
node.h
#pragma once
#include <string>
using namespace std;
class node
{
public:
// Default Constructor
// Values, "none", "none", NULL.
node();
// Parameterized Constructor
// nextNode initialized NULL and must be explicitly set.
node(string descriptionInput, string quantityInput);
// getDescription function
// Purpose: Returns node description.
// Returns: string
// Pre-Conditions: None.
// Post-Conditions: None.
string getDescription();
// setDescription function
// Purpose: Sets node description
// Returns: Void
// Pre-Conditions: None
// Post-Conditions: None
void setDescription(string);
// getQuantity function
// Purpose: Returns node quantity.
// Returns: string
// Pre-Conditions: None.
// Post-Conditions: None.
string getQuantity();
// setQuantity function
// Purpose: Sets node quantity
// Returns: Void
// Pre-Conditions: None
// Post-Conditions: None
void setQuantity(string);
// getNextNode function
// Purpose: Returns pointer to next node in list sequence.
// Returns: node pointer
// Pre-Conditions: None.
// Post-Conditions: None.
// Note: Not set during initialization. Must be explicitly done.
node* getNextNode();
// setNextNode function
// Purpose: Sets pointer to next node in list sequence.
// Returns: None.
// Pre-Conditions: None.
// Post-Conditions: None.
// Note: Not set during initialization. Must be explicitly done.
void setNextNode(node*);
private:
string description;
string quantity;
node* nextNode;
};
node.cpp
#include "node.h"
node::node()
:description("none"),
quantity("none"),
nextNode(NULL)
{}
node::node(string descriptionInput, string quantityInput)
:description(descriptionInput),
quantity(quantityInput),
nextNode(NULL)
{}
string node::getDescription()
{
return description;
}
void node::setDescription(string descriptionInput)
{
description = descriptionInput;
}
string node::getQuantity()
{
return quantity;
}
void node::setQuantity(string quantityInput)
{
quantity = quantityInput;
}
node* node::getNextNode()
{
return nextNode;
}
void node::setNextNode(node* input)
{
nextNode = input;
}
linklist.h
#pragma once
#include "node.h"
class linklist
{
public:
// Constructor
// Builds an empty list
linklist();
// push_front function
// Purpose: Takes node pointer. Places that node at beginning of list.
// Returns: None
// Pre-Conditions: None
// Post-Conditions: None
void push_front(node*);
// pop_front function
// Purpose: Removes first node from list.
// Returns: Node pointer. NODE IS NOT DESTROYED.
// Pre-Conditions: List must have a node to remove.
// Post-Conditions: Node is not destroyed.
node* pop_front();
// getFirst function
// Purpose: Returns node pointer to first node in list
// Returns: node pointer
// Pre-Conditions: List must have a node added.
// Post-Conditions: None.
node* getFirst();
// push_back function
// Purpose: Takes node pointer. Places that node at end of list.
// Returns: None
// Pre-Conditions: None
// Post-Conditions: None
void push_back(node*);
// pop_back function
// Purpose: Removes last node from list.
// Returns: Node pointer. NODE IS NOT DESTROYED.
// Pre-Conditions: List must have a node to remove.
// Post-Conditions: Node is not destroyed.
node* pop_back();
// getNodeCount function
// Purpose: Returns nodeCount
// Returns: int
// Pre-Conditions: None.
// Post-Conditions: None.
int getNodeCount();
private:
node* firstNode;
node* lastNode;
int nodeCount;
};
linklist.cpp
#include "linklist.h"
linklist::linklist()
:firstNode(NULL),
lastNode(NULL),
nodeCount(0)
{}
void linklist::push_front(node* input)
{
node* temp = getFirst();
input->setNextNode(temp);
firstNode = input;
nodeCount++;
}
node* linklist::pop_front()
{
node* temp = getFirst();
firstNode = temp->getNextNode();
nodeCount--;
return temp;
}
node* linklist::getFirst()
{
return firstNode;
}
void linklist::push_back(node* input)
{
node* temp = lastNode;
temp->setNextNode(input);
lastNode = temp;
nodeCount++;
}
node* linklist::pop_back()
{
node* oldLast = lastNode;
node* temp = firstNode;
// find second to last node, remove it's pointer
for (int i = 0; i < (nodeCount - 1); i++)
{
temp = temp->getNextNode();
}
temp->setNextNode(NULL);
lastNode = temp;
nodeCount--;
return oldLast;
}
int linklist::getNodeCount()
{
return nodeCount;
}
Having trouble getting one portion of my code to work. Building a rudimentary linked list to learn pointers. I think I have most of it down, but any attempts to use a function I created (push_back) throws memory access errors on setting a value for a pointer.
Not exactly sure what's wrong, because it works fine to use push_front, which work almost exactly the same.
Any ideas? =/
CODE:
driver.cpp
#include <string>
#include <iostream>
#include "linklist.h"
#include "node.h"
using namespace std;
// printList function
// Purpose: Prints each node in a list
// Returns: None.
// Pre-Conditions: List must have member nodes.
// Post-Conditions: None.
void printList(linklist);
int main()
{
linklist grocery;
grocery.push_front(new node("milk", "1 gallon"));
grocery.push_front(new node("bread","2 loaves"));
grocery.push_front(new node("eggs","1 dozen"));
grocery.push_front(new node("bacon","1 package"));
cout << "First iteration:" << endl;
printList(grocery);
cout << "----------------------" << endl << endl;
grocery.push_front(new node("hamburger","2 pounds"));
grocery.push_front(new node("hamburger buns", "1 dozen"));
cout << "Second iteration:" << endl;
printList(grocery);
cout << "----------------------" << endl << endl;
node* deleteMe = grocery.pop_front();
delete deleteMe;
cout << "Third iteration:" << endl;
printList(grocery);
cout << "----------------------" << endl << endl;
grocery.push_back(new node("orange juice","2 cans"));
grocery.push_back(new node("swiss cheeese","1 pound"));
cout << "Fourth iteration:" << endl;
printList(grocery);
cout << "----------------------" << endl << endl;
deleteMe = grocery.pop_back();
delete deleteMe;
cout << "Fifth iteration:" << endl;
printList(grocery);
cout << "----------------------" << endl << endl;
while (grocery.getNodeCount() != 0)
{
deleteMe = grocery.pop_front();
cout << "Cleaning: " << deleteMe->getDescription() << endl;
delete deleteMe;
}
system("PAUSE");
return 0;
}
void printList(linklist input)
{
node* temp = input.getFirst();
for (int i = 0; i < (input.getNodeCount()); i++)
{
cout << temp->getQuantity() << " " << temp->getDescription() << endl;
temp = temp->getNextNode();
}
}
node.h
#pragma once
#include <string>
using namespace std;
class node
{
public:
// Default Constructor
// Values, "none", "none", NULL.
node();
// Parameterized Constructor
// nextNode initialized NULL and must be explicitly set.
node(string descriptionInput, string quantityInput);
// getDescription function
// Purpose: Returns node description.
// Returns: string
// Pre-Conditions: None.
// Post-Conditions: None.
string getDescription();
// setDescription function
// Purpose: Sets node description
// Returns: Void
// Pre-Conditions: None
// Post-Conditions: None
void setDescription(string);
// getQuantity function
// Purpose: Returns node quantity.
// Returns: string
// Pre-Conditions: None.
// Post-Conditions: None.
string getQuantity();
// setQuantity function
// Purpose: Sets node quantity
// Returns: Void
// Pre-Conditions: None
// Post-Conditions: None
void setQuantity(string);
// getNextNode function
// Purpose: Returns pointer to next node in list sequence.
// Returns: node pointer
// Pre-Conditions: None.
// Post-Conditions: None.
// Note: Not set during initialization. Must be explicitly done.
node* getNextNode();
// setNextNode function
// Purpose: Sets pointer to next node in list sequence.
// Returns: None.
// Pre-Conditions: None.
// Post-Conditions: None.
// Note: Not set during initialization. Must be explicitly done.
void setNextNode(node*);
private:
string description;
string quantity;
node* nextNode;
};
node.cpp
#include "node.h"
node::node()
:description("none"),
quantity("none"),
nextNode(NULL)
{}
node::node(string descriptionInput, string quantityInput)
:description(descriptionInput),
quantity(quantityInput),
nextNode(NULL)
{}
string node::getDescription()
{
return description;
}
void node::setDescription(string descriptionInput)
{
description = descriptionInput;
}
string node::getQuantity()
{
return quantity;
}
void node::setQuantity(string quantityInput)
{
quantity = quantityInput;
}
node* node::getNextNode()
{
return nextNode;
}
void node::setNextNode(node* input)
{
nextNode = input;
}
linklist.h
#pragma once
#include "node.h"
class linklist
{
public:
// Constructor
// Builds an empty list
linklist();
// push_front function
// Purpose: Takes node pointer. Places that node at beginning of list.
// Returns: None
// Pre-Conditions: None
// Post-Conditions: None
void push_front(node*);
// pop_front function
// Purpose: Removes first node from list.
// Returns: Node pointer. NODE IS NOT DESTROYED.
// Pre-Conditions: List must have a node to remove.
// Post-Conditions: Node is not destroyed.
node* pop_front();
// getFirst function
// Purpose: Returns node pointer to first node in list
// Returns: node pointer
// Pre-Conditions: List must have a node added.
// Post-Conditions: None.
node* getFirst();
// push_back function
// Purpose: Takes node pointer. Places that node at end of list.
// Returns: None
// Pre-Conditions: None
// Post-Conditions: None
void push_back(node*);
// pop_back function
// Purpose: Removes last node from list.
// Returns: Node pointer. NODE IS NOT DESTROYED.
// Pre-Conditions: List must have a node to remove.
// Post-Conditions: Node is not destroyed.
node* pop_back();
// getNodeCount function
// Purpose: Returns nodeCount
// Returns: int
// Pre-Conditions: None.
// Post-Conditions: None.
int getNodeCount();
private:
node* firstNode;
node* lastNode;
int nodeCount;
};
linklist.cpp
#include "linklist.h"
linklist::linklist()
:firstNode(NULL),
lastNode(NULL),
nodeCount(0)
{}
void linklist::push_front(node* input)
{
node* temp = getFirst();
input->setNextNode(temp);
firstNode = input;
nodeCount++;
}
node* linklist::pop_front()
{
node* temp = getFirst();
firstNode = temp->getNextNode();
nodeCount--;
return temp;
}
node* linklist::getFirst()
{
return firstNode;
}
void linklist::push_back(node* input)
{
node* temp = lastNode;
temp->setNextNode(input);
lastNode = temp;
nodeCount++;
}
node* linklist::pop_back()
{
node* oldLast = lastNode;
node* temp = firstNode;
// find second to last node, remove it's pointer
for (int i = 0; i < (nodeCount - 1); i++)
{
temp = temp->getNextNode();
}
temp->setNextNode(NULL);
lastNode = temp;
nodeCount--;
return oldLast;
}
int linklist::getNodeCount()
{
return nodeCount;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您在推送方法中存在错误,因为当您在前面推送时,您无法控制该元素是否也是最后一个元素,并且当您在末尾推送时也类似。它导致您没有连接整个列表,因为开始部分不知道结束部分。我希望这是可以理解的。
弹出方法也是错误的 - 同样的问题。您无法控制列表是否为空
You have mistakes in push methods, because when you are pushing at front you don't control if this element is also the last one and similary when you are pushing at the end. It causes that you don't have connected whole list, because the beginning part don't know about ending part. I hope that this is understandable.
Also pop methods are wrong - same problem. You don't control if the list is empty
根据
node
的定义,它是一个单链表。 (否则您还必须包含prevNode
)。因此,操纵列表的“后面”并非易事。要弹出列表的“后面”,您需要遍历整个列表并识别新的“最后”元素。
你确定你做对了吗?包括处理所有“极端”情况(例如删除最后一个元素等)?
最好发布
push_back
和pop_back
的代码。PS 也许您没有在
push_front
和pop_front
中正确设置lastNode
。除非你试图操纵你的“背部”,否则你可能不会注意到这一点。把
push_front
和pop_front
的代码也贴出来。编辑:
好的,我看到代码了。而且还有很多错误。
According to
node
's definition it's a single-linked list. (otherwise you'd have to contain alsoprevNode
).Hence - manipulating the "back" of your list is non-trivial. To pop the "back" of your list you'll need to transverse the entire list and identify the new "last" element.
Are you sure you do this right? Including handling all the "extremal" cases (like removing last element and etc.)?
It'd be nice to post the code of
push_back
andpop_back
.P.S. Perhaps you don't set
lastNode
correctly in yourpush_front
andpop_front
. You may not notice this unless you're trying to manipulate your "back".Post the code of
push_front
andpop_front
as well.EDIT:
Alright, I see the code. And there're plenty of errors.
看起来你的push_back中有一个简单的错误:
如上所述,我认为你的意思是
lastNode = input
;ps 仔细考虑“异常安全”。 pop 例程不返回任何内容,而是与 peek() 例程配对,以支持异常中立性/安全性,这种情况并不罕见。
It looks like you've got one simple error in your push_back:
As annotated above, I think you meant
lastNode = input
;p.s. Take "exception safety" carefully into account. It is not uncommon for pop routines to return nothing, and instead be paired with a peek() routine, in order to support exception neutrality / safety.
好吧,当列表为空时,
push_back
中的temp
为NULL。因此temp->setNextNode(input)
失败。您需要区分空列表的特殊情况。顺便问一下,如果你允许前后操作,也许你需要一个双向链表?否则,您需要遍历整个(可能很大)列表才能弹出最后一个元素,因为您没有指向其前一个元素的“直接”链接。
顺便说一句,您的操作是双端队列的操作,而不是列表的操作。
Well, when the list is empty, in
push_back
temp
is NULL. Thereforetemp->setNextNode(input)
fails. You need to distinguish the special case of empty list.By the way, if you allow the operations on both back and front, perhaps you need a doubly-linked list? Otherwise you'll need to traverse the whole (potentially huge) list in order to pop the last element, as you don't have a "direct" link to its previous element.
By the way, your operations are that of the deque, not the list.