c++ Linked List losing data between functions

江枫思渺然 提交于 2020-01-04 06:26:11

问题


I am having a problem with pointers and scope. I am trying to maintain an array of linked lists of pointers to objects. When I try to push_front() in one function, it works. However, if I try to iterate through the list in another part of my program, the list no longer contains any data, and my pointers are bad.

This is part of my parseCommands function. the problem is when printList is called:

                    Administrator *adminPtr = new Administrator(); // create new Administrator pointer

                    //local variables...
                    string adminName;   //administrator's name
                    int adminMNum;  //administrator's M Number
                    string adminEmail;  //administrator's email address
                    string adminTitle;  // administrator's title

                    // read in & store data for new administrator
                    inData >> adminName; //read in data
                    adminPtr->setName(adminName); //set admin name

                    inData >> adminMNum;
                    adminPtr->setMNum(adminMNum);   // set admin M Number

                    inData >> adminEmail;
                    adminPtr->setEmail(adminEmail); // set admin email address

                    inData >> adminTitle;
                    adminPtr->setTitle(adminTitle); //set admin title
                    // finished storing new administrator info

                    // add Administrator to list
                    cout << "Adding Administrator: " << endl;
                    cout << "in records office adminPtr/newPerson: " << adminPtr << endl;
                    universityList.addPerson(adminPtr);  // call addPerson--hashTable
                    //universityList.printPerson(adminPtr);     // print admin info using polymorphic method
                    //cout << "The load factor (alpha) is: " << universityList.getLength()/universityList.getMaxTableSize() << endl;    // print alpha
                    universityList.printList(adminPtr->getMNum());  // print all items at table[loc]--breaks here
                    cout << endl;               

The addPerson function where printList works fine:

template <typename T>
void HashTable<T>::addPerson(T newPerson) { //newPerson is a pointer to a person object
  int loc;  // array location provided by hashFunction
  cout << "in hashtable newPerson: " << newPerson << endl;
  loc = hashFunction(newPerson->getMNum());  // get loc
  table[loc].push_front(&newPerson);  // add to list at table[loc] passing address of pointer to person
  printList(newPerson->getMNum());  // print all items at table[loc]--works here
  size++;   // increment size
  } //end function

The printList function that works when called in addPerson, but not in parseCommands:

template <typename T>
void HashTable<T>::printList(searchKeyType key) {   //print list of items held in array location
    int loc = hashFunction(key);    // get array location
    if (table[loc].empty()) {   // if list is empty
        cout << "Can not print person M" << key << " NOT found" << endl << endl; 
    }   //end if empty
  else{
    list<T*>::iterator iter;    // stl iterator
    iter = table[loc].begin();
    cout << "in printList table[loc]begin " << *iter << endl;   //print address of table[loc]begin.()--where iter points
    cout << "in printList item in table[loc]begin " << **iter << endl;  // print address of the pointer that iter points to
    while(iter != table[loc].end()) { // for each item in the list

        (**iter)->print();  // print person info using polymorphic method
        ++iter;
    }   //end for
  } // end else
}   // end printList

The print function:

void Administrator::print()const {  
// print Administrator info
cout << "   " << "Full Name:    " << getName() << endl;
cout << "   " << "M Number :    "<< getMNum() << endl;
cout << "   " << "Email Addr:   " << getEmail() << endl;
cout << "   " << "Title:        "   << getTitle() << endl;
}; // end print function

The hashTable class:

template<typename T>
class HashTable{
public:
    HashTable(); // constructor
    bool isEmpty()const; //determines if the hash table is empty
    int getLength() const;  // returns (size) number of Persons in table (accessor)
    int getMaxTableSize() const;    // returns tableSize (size of array)
    void addPerson(T person);   // adds new Person 
    void removePerson(searchKeyType key);   // deletes Person from the HashTable
    void printPerson(T person); // prints Person info
    T getNodeItem(int mNumber); //returns person object (accessor)
    void printList(searchKeyType key);  //print list of items held in array location

private:
    int size;   // number of Persons in table
    static const int tableSize = 1; // number of buckets/array size -- planning on using 70001--assuming 35,000 entries at once; largest prime > 2*35000
    list <T*> table[tableSize]; // array of STL lists for chains
    int hashFunction(searchKeyType searchKey);  // hash function to return location (array index) of item
}; //end HashTable class

I pass adminPtr to addPerson, and it seems to add it to the list. Why am I losing the data when I return to the parseCommands function? Is it a stack vs. heap issue? Do I need "new" somewhere? There are a few extra lines in there where I was printing out the address of the pointers trying to figure out what's going on.

This was a programming problem for a class that I was unable to resolve. We had to simulate a hash table using an array of STL linked lists. We were not allowed to use vectors, maps, etc. The program involves an abstract base class (Person) with derived classes (Administrator, etc.) and a templated hash table class. There is one more class (RecordsOffice) that holds the hash table.

class RecordsOffice {
public:
    RecordsOffice();    // default constructor
    void parseCommands(string fileName);    // function to parse commands from a file to maintain the StudentList

private:
    HashTable <Person*> universityList; // creates empty hashtable
};

回答1:


The problem is in these two places.

universityList.addPerson(adminPtr); 

//...

You are passing a copy of adminPtr.

template <typename T>
void HashTable<T>::addPerson(T newPerson) { //newPerson is a pointer to a person object
// ...
  table[loc].push_front(&newPerson);  // add to list at table[loc] passing address of pointer to person
// ....
  } 

newPerson is a local variable to addPerson. When it returns it is no more valid. But you are adding it´s address in to the table.

the issue is that

list <T*> table[tableSize];

is storing pointers to pointers of Person.

I don't think passing by reference would solve the problem too. Because then you will be dependent on the automatically created pointer here.

Administrator *adminPtr = new Administrator();

What adminPtr pointer points to will stay but not adminPtr itself. So you can not depend on its address (unless you are sstill in the same function that created it). One possible way to solve it would be to allocate adminPtr itself dynamically.

Administrator **adminPtr = new Administrator*;
adminPtr = new Administrator();

But maybe you should revise the requirements.




回答2:


Your table is declared like this:

list <T*> table[tableSize];

That means any pointers it contains need to be dynamically allocated, or need to remain in scope for the entire lifetime of the container. This is not the case. In your function addPerson you add the address of a local variable:

table[loc].push_front(&newPerson);

You should do one of the following:

  1. Change the table to an array of list<T> objects.
  2. Copy the data dynamically. eg table[loc].push_front(new T(newPerson))

Because this is a list, I would go for option 1 because the list will copy locally anyway, and you won't have to clean up the pointers later. A third option would be to use list<unique_ptr<T> > or similar.



来源:https://stackoverflow.com/questions/15959325/c-linked-list-losing-data-between-functions

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!