0

ファンクターを使用していくつかの int をソートするこのプログラムを作成しました。

#include<iostream>
#include<list>
#include<set>

using namespace std;

struct IntSorter
{
    unsigned int comparisons;
    IntSorter()
    {
        std::cout << "new intsorter" << std::endl;
        comparisons = 0;
    }

    bool operator() (const int &a, const int &b)
    {
        std::cout << "c is " << comparisons << std::endl;
        ++comparisons;
        std::cout << "c is now " << comparisons << std::endl;
        return a<b;
    }
};

int main(int argc, char *argv[])
{    
    list<int> my_list;
    my_list.push_back(4);
    my_list.push_back(3);
    my_list.push_back(5);
    my_list.push_back(1);

    IntSorter s;
    my_list.sort(s);

    for (list<int>::iterator it=my_list.begin(); it!=my_list.end(); it++)
    {
        std::cout << *it << std::endl;
    }

    return 0;

}

並べ替えは正常に機能しますが、比較の数をカウントする部分では、予期しない結果が得られます。

./prog -a -b -c -d
new intsorter
c is 0
c is now 1
c is 0
c is now 1
c is 0
c is now 1
c is 1
c is now 2
c is 2
c is now 3
1
3
4
5

私は構造が再利用され、比較の数を数えて保存すると思っていました。ただし、出力された数字が 1,2,3,4,5 ではなく 1,1,1,2,3 になるため、それをコピーするか、その他の動作をしているように見えます。私は何を間違っていますか?

4

3 に答える 3

3

あなたは正しい軌道に乗っています。std::list::sort は関数オブジェクトを値で受け取ります。関数オブジェクトのコピーを渡します。これは、比較メンバー データもコピーされることを意味します。

あなたは何も悪いことをしていません。それは、このようなファンクターを使用できないということだけです。

std::list::sort を実行させる最も簡単な方法は、ファンクターに外部カウンター オブジェクトへの参照を埋め込むことです。比較のたびに、そのカウンター オブジェクトへの呼び出しを転送します。std::list::sort が戻った後、そこに合計が表示されます。

于 2009-10-16T19:37:15.623 に答える
2

あなたは本当に何も悪いことをしていません。問題は完全にあなたの期待にあります-ソーターは値で渡されるため、渡すと最低でも1つのコピーが作成されます。sort 関数は、自由にコピーを作成することもできます (たとえば、再帰ソートは、再帰呼び出しごとにコピーを渡す可能性があります)。

ここで簡単な教訓があります。そのようなオブジェクトは、安価に作成および/またはコピーする必要があります。

于 2009-10-16T19:32:32.977 に答える
0

言及したように、それは値によって渡されます: 簡単な解決策は次のとおりです。

struct IntSorter
{
    unsigned int& comparisons;
    IntSorter(unsigned int& c)
        :comparisons(c)
    {}
    // Other Stuff
};

// In main:
unsigned int  count = 0;
my_list.sort(IntSorter(count));
于 2009-10-16T22:05:28.267 に答える