2

我遇到了指针和范围的问题。我正在尝试维护一组指向对象的指针链表。当我尝试在一个函数中 push_front() 时,它可以工作。但是,如果我尝试在程序的另一部分中遍历列表,则列表不再包含任何数据,并且我的指针是错误的。

这是我的 parseCommands 函数的一部分。问题是调用 printList 时:

                    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;               

printList 工作正常的 addPerson 函数:

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

printList 函数在 addPerson 中调用时起作用,但在 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

打印功能:

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

哈希表类:

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

我将 adminPtr 传递给 addPerson,它似乎将其添加到列表中。为什么当我返回到 parseCommands 函数时会丢失数据?这是堆栈与堆的问题吗?我在某个地方需要“新”吗?那里有几行额外的行,我在其中打印出指针的地址,试图弄清楚发生了什么。

这是一个我无法解决的类的编程问题。我们必须使用一组 STL 链表来模拟哈希表。我们不允许使用向量、映射等。该程序涉及一个抽象基类(Person)和一个派生类(Administrator 等)和一个模板化的哈希表类。还有一个类(RecordsOffice)保存哈希表。

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

2 回答 2

1

问题出在这两个地方。

universityList.addPerson(adminPtr); 

//...

您正在传递 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是 的局部变量addPerson。当它返回时,它不再有效。但是您正在将其地址添加到表中。

问题是

list <T*> table[tableSize];

正在存储指向 Person 指针的指针。

我不认为通过引用传递也可以解决问题。因为那时你将依赖这里自动创建的指针。

Administrator *adminPtr = new Administrator();

adminPtr指针指向的将保留,但不会保留它adminPtr 本身。所以你不能依赖它的地址(除非你仍然在创建它的同一个函数中)。解决它的一种可能方法是动态分配 adminPtr 本身。

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

但也许你应该修改要求。

于 2013-04-11T21:45:44.767 回答
1

你的表是这样声明的:

list <T*> table[tableSize];

这意味着它包含的任何指针都需要动态分配,或者需要在容器的整个生命周期内保持在范围内。不是这种情况。在您的函数addPerson中,您添加一个局部变量的地址:

table[loc].push_front(&newPerson);

您应该执行以下操作之一:

  1. list<T>将表更改为对象数组。
  2. 动态复制数据。例如 table[loc].push_front(new T(newPerson))

因为这是一个列表,所以我会选择选项 1,因为该列表无论如何都会在本地复制,并且您以后不必清理指针。第三种选择是使用list<unique_ptr<T> >或类似的。

于 2013-04-11T21:46:48.730 回答