0

我编写了这个程序,它使用仿函数对一些整数进行排序:

#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、1、1、2、3,而不是 1、2、3、4、5。我究竟做错了什么?

4

3 回答 3

3

你在正确的轨道上。std::list::sort 按值获取函数对象。当它工作时,它会传递你的函数对象的副本,这意味着比较成员数据也会被复制。

你没有做错什么,只是你不能使用这样的函子。

让 std::list::sort 做你想做的最简单的方法是在你的仿函数中嵌入对外部计数器对象的引用。在每次比较时,将调用转发到该计数器对象。在 std::list::sort 返回后,您将在那里获得总数。

于 2009-10-16T19:37:15.623 回答
2

你真的没有做错什么。问题完全在于您的期望——分拣机是按值传递的,因此在您传递它时至少会制作一份副本。排序函数也可以自由地制作更多副本(例如,递归排序可能会将副本传递给每个递归调用)。

这里有一个简单的教训:任何此类对象的创建和/或复制都应该很便宜。

于 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 回答