C++函子 - 意外的行为?
我编写了这个程序,它使用函子对一些整数进行排序:
#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。我做错了什么?
I have written this program, which sorts some ints using a functor:
#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;
}
The sorting works fine, but the part counting the number of comparisons gives a result I didn't expect:
./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
I was thinking the structure would be reused, counting and storing the number of comparisons. However, it appears to copy it, or some other behaviour as the numbers printed out go 1,1,1,2,3, instead of 1,2,3,4,5. What am I doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
你走在正确的轨道上。 std::list::sort 按值获取函数对象。当它完成工作时,它会传递函数对象的副本,这意味着比较成员数据也会被复制。
你没有做错什么,只是你不能使用这样的函子。
让 std::list::sort 执行您想要的操作的最简单方法是在函子中嵌入对外部计数器对象的引用。每次比较时,将调用转发到该计数器对象。 std::list::sort 返回后,您将在其中看到总数。
You're on the right track. std::list::sort takes the function object by value. As it does its work, it passes a copy of your function object around which means that the comparisons member data is getting copied, too.
You're not doing anything wrong, it's just that you can't use a functor like this.
The easiest way to make std::list::sort do what you want is to embed a reference to an external counter object in your functor. On each comparison, forward a call to that counter object. After std::list::sort returns, you'll have the total in there.
你其实并没有做错什么。问题完全在于您的期望 - 排序器是按值传递的,因此当您传递它时,至少会生成一份副本。排序函数也可以自由地创建更多副本(例如,递归排序可能会向每个递归调用传递一个副本)。
这里有一个简单的教训:任何此类对象的创建和/或复制都应该便宜。
You're not really doing anything wrong. The problem lies entirely in your expectation -- the sorter is passed by value, so there's a bare minimum of one copy made as you pass it. The sort function is free to make more copies as well (e.g. a recursive sort will probably pass a copy to each recursive invocation).
There's a simple lesson here: any such object should be cheap to create and/or copy.
如前所述,它是按值传递的:
一个简单的解决方案是:
As mention it is passed by value:
A simple solution is: