设置对象属性时C ++内存访问冲突

时间:2010-11-25 22:04:10

标签: c++ pointers object user-defined-functions

无法让我的代码的一部分工作。建立一个基本的链表来学习指针。我想我的大部分内容已经失效,但是任何尝试使用我创建的函数(push_back)都会在设置指针值时抛出内存访问错误。

不确定是什么问题,因为它可以正常使用push_front,它几乎完全相同。

有什么想法吗? = /

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;
}

4 个答案:

答案 0 :(得分:2)

你在推送方法上有错误,因为当你在前面推动时,你不能控制这个元素是否也是最后一个,并且当你在最后推动时是相似的。它导致你没有连接整个列表,因为开始部分不知道结束部分。我希望这是可以理解的。

同样流行的方法是错误的 - 同样的问题。您无法控制列表是否为空

答案 1 :(得分:1)

好吧,当列表为空时,push_back temp为NULL。因此temp->setNextNode(input)失败。您需要区分空列表的特殊情况。

顺便说一下,如果你允许后面和前面的操作,也许你需要一个双向链表?否则,您需要遍历整个(可能很大的)列表以弹出最后一个元素,因为您没有到其前一个元素的“直接”链接。

顺便说一句,你的操作是deque的操作,而不是列表。

答案 2 :(得分:1)

看起来你的push_back中有一个简单的错误:

void linklist::push_back(node* input) 
{ 
   node* temp = lastNode; 

   temp->setNextNode(input); 

   lastNode = temp; //this looks wrong
   nodeCount++; 
} 

如上所述,我认为你的意思是lastNode = input;

P.S。以"exception safety" carefully into account为准。 pop例程不返回任何内容,而是与peek()例程配对,以支持异常中立性/安全性并不罕见。

答案 3 :(得分:1)

根据node的定义,它是一个单链表。 (否则你还必须包含prevNode)。

因此 - 操纵列表的“后退”并非易事。要弹出列表的“后退”,您需要横切整个列表并识别新的“最后”元素。

你确定你这样做了吗?包括处理所有“极端”情况(如删除最后一个元素等)?

发布push_backpop_back的代码非常好。

P.S。也许您没有在lastNodepush_front中正确设置pop_front。你可能不会注意到这一点,除非你试图操纵你的“后退”。

也发布push_frontpop_front的代码。

修改

好的,我看到了代码。而且有很多错误。

void linklist::push_front(node* input)
{
    node* temp = getFirst();

    input->setNextNode(temp);

    firstNode = input;
    nodeCount++;

    // Missing:
    if (!temp)
        lastNode = firstNode;
}


node* linklist::pop_front()
{
    node* temp = getFirst();

    firstNode = temp->getNextNode();

    // Missing:
    if (!firstNode)
        lastNode = 0;

    nodeCount--;
    return temp;
}


void linklist::push_back(node* input)
{
    node* temp = lastNode;

    // instead of
    // temp->setNextNode(input);
    // lastNode = temp;

    // should be:
    if (temp)
        temp->setNextNode(input);
    else
        firstNode = input;

    lastNode = input;

    nodeCount++;
}

node* linklist::pop_back()
{
    node* oldLast = lastNode;

    if (firstNode == lastNode)
    {
        firstNode = 0;
        lastNode = 0;
    } else
    {
        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;
}