从函数返回后对象值发生了变化

时间:2012-11-16 05:34:55

标签: c++ list stl

家庭作业的一部分

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

我在列表中添加了10个对象,值为0到3.当我搜索除0之外的任何数字(./a.out 1 OR ./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;
}

1 个答案:

答案 0 :(得分: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;
}