0

宿題の一部

私はオブジェクトのリストを持っています。私の目標は、オブジェクト X がそのリストに存在するかどうかを試して見つけることです (そのオブジェクトの最初の出現のみに関心があります)。私のコードはほとんどの部分で正常に動作しているようですが、関数から返された後に特定のオブジェクトの値が 1 つだけ変更されているという奇妙なエラーがあります。

0 から 3 までの値を持つ 10 個のオブジェクトをリストに追加しました。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;
}
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 に答える