自定义比较函数用 函数对象或lamda表达式 代替比较函数

【1】

说明:在使用stl库中的查找和排序时,往往会使用自定义比较函数。使用函数对象的方式比传输函数指针的方式具有更好的性能。lamba表达式的行为类似于带有()运算符的函数对象,性能均优于比较函数。

引申——斯特潘诺夫的抽象惩罚:C++标准库提供的直接可用的算法和数据结构,能适用于很多情况,但即使是最优秀的标准库算法,往往无法与最佳的手工编写算法匹敌。即为斯特潘诺夫的抽象惩罚。

【2】C++ unordered_map中如何传入lambda对象作为hash函数?

为何使用hash_fun作为参数传入unordered_map时执行正常,传入lambda作为hash函数时出现运行时错误?代码如下:

解答:

1、定义时没有传入hash_lambda的实例引用,只是定义了模板参数hash的类型是不够的。改成下面这样就没错了:

unordered_map<pair<int, int>, int, decltype(hash_lambda)> lambda_map(hash_lambda);

2、直接传入lambda编译出错的原因:每个lambda都对应一个匿名的类型,但是这个产生的类不含默认构造函数,赋值运算符和默认析构函数。当unordered_map使用lambda匿名类型去默认构造Hash实例时失败报错。所以,只将lambda对应的类型传给unordered_map,unordered_map无法使用这个匿名类型构造Hash实例。  传入functional实例类型,编译正常,运行出错的原因:传入的function<size_t (const pair<int, int>&)>类型,具有默认构造函数,能够构造一个空的function对象;所有编译能够正常,但是执行时抛出异常。我们需要手动传入hash函数实例引用。

3、为什么直接传入函数对象hash_fun 可行呢?答案隐藏在unordered_map的实现细节里:
简单来说,unordered_map继承自_Hash类,_Hash类有一个细节就是用到一个_Uhash_compare类来封装传入的hash函数,如果unordered_map构造函数没有给出hash函数实例引用,则默认通过指定的模板参数类Hash的缺省构造函数构造一个,在第一种情况下也就是hash_fun()。而第二种情况下就是function<size_t(const pair<int, int>&)>(),这就不对了,于是我们就看到了std:bad_function_call异常。这个异常正是std:function类抛出的,其描述如下:

std::bad_function_call is the type of the exception thrown by std::function::operator() if the function wrapper has no target.

发布了19 篇原创文章 · 获赞 2 · 访问量 199

猜你喜欢

转载自blog.csdn.net/qfturauyls/article/details/102989947
今日推荐