0

家庭作业问题的一部分

我有一个对象列表,我的目标是尝试查找该列表中是否存在对象 X(我只对该对象的第一次出现感兴趣)。我的代码在大多数情况下似乎工作正常,但我有一个奇怪的错误,其中只有 1 个特定对象的值在从函数返回后被修改。

我在列表中添加了 10 个对象,其值为 0 到 3。当我搜索除 0 以外的任何数字时,(./a.out 1 或 ./a.out 2 等)我得到正确的输出。但是当我搜索 0(./a.out 0) 时,findInList() 会打印出正确的结果,但 main() 会打印出值 18(甚至不在列表中)。

我在这里附上完整的源代码,以防有人想编译它并尝试一下。我还附上了我所做的gdb步骤。

来源:

#include <iostream>
#include <string>
#include <functional>
#include <list>
using namespace std;

class Page {
public:
    int pgnum; // page number
    union {
        int lfu_count;
        int lru_clock:1; // can only be 0/1
        int lru_ref8:8;  // we only need 8 bits
    };

public:
    // Constructors
    Page(int num)       { pgnum = num; }
    Page()              {}

    // Operator overloading
    bool operator== (const Page &p) const { 
        if(p.pgnum == pgnum)
            return true;
        else
            return false;
    }
    bool operator!= (const Page &p) const { 
        return !(p==*this);
    }
};

ostream & operator<<(ostream & os, const Page &p) {
    os << "Page number: " << p.pgnum;
    return os;
}

// Think of this as an equivalent to equals in Java (IT IS NOT, JUST IMAGINE)
struct PageNumber: public binary_function< Page, Page, bool > {
    bool operator () ( const Page &p1, const Page &p2 ) const {
        return p1 == p2;
    }
};

// Function to find an object in any list given an Operation
template <class Operation, class T>
T* findInList( list<T> fullList, T obj, const Operation &op ) {
    T* ret = NULL;
    typename list<T>::iterator it = fullList.begin();
    it = find_if( it, fullList.end(), bind2nd( op, obj ) );
    if( it != fullList.end() ) {
        cout << "Found obj in list: " << *it << endl;
        ret = &(*it); // not the same as it (which is of type iterator)
    }
    return ret;
}

int main( int argc, char **argv ) {
    Page page_to_find;
    list<Page> frames;

    if( argc != 2 ) {
        cout << "Please enter 1 and only 1 argument" << endl;
        exit(-1);
    }
    page_to_find.pgnum = atoi(argv[1]);

    Page *p = new Page[10];
    for( int i=0; i<10; i++ ) {
        p[i].pgnum = i%4;
        frames.push_back(p[i]);
    }

    list<Page>::iterator it_frames = frames.begin();
    while( it_frames != frames.end() ) {
        cout << "Page in frames: " << *it_frames << endl;
        it_frames++;
    }

    Page* pg = findInList( frames, page_to_find, PageNumber() );
    if( pg != NULL )
        cout << "Found page: " << *pg << endl;

    delete[] p;

    return 0;
}
4

1 回答 1

1

您将返回列表中对象的地址,该列表按值推入参数列表。因此,这是未定义的行为。考虑将列表的参数更改为findInList引用。

// note reference type change in parameter list.
template <class Operation, class T>
T* findInList( list<T>& fullList, T obj, const Operation &op ) {
    T* ret = NULL;
    typename list<T>::iterator it = fullList.begin();
    it = find_if( it, fullList.end(), bind2nd( op, obj ) );
    if( it != fullList.end() ) {
        cout << "Found obj in list: " << *it << endl;
        ret = &(*it); // not the same as it (which is of type iterator)
    }
    return ret;
}
于 2012-11-16T05:52:22.550 回答