繁体   English   中英

比较 Function 是否在 std::sort 返回布尔类型中与 lambda function 指定?

[英]Does Comparison Function specified with lambda function in std::sort return bool type?

我正在阅读这段代码(来源):

#include <iostream> 
#include <functional>
#include <algorithm>
using namespace std; 

int main() { 
    int number[] = {3, 5, 1, 6, 9};
    auto print = [](int n) { cout << n << " "; };

    sort(begin(number), end(number), [](int n1, int n2) { return n2 - n1; });
    // result: 9 6 1 5 3
    for_each(begin(number), end(number), print);
    cout << endl;

    sort(begin(number), end(number), [](int n1, int n2) { return n1 - n2; });
    // result: 3 5 1 6 9
    for_each(begin(number), end(number), print);
    cout << endl;

    return 0; 
} 

我对如何return n2 - n1; vs return n1 - n2; 工作。

根据std::sort - cppreference.com ,它说comp是布尔类型function。 在 C++ 中,非零数始终具有真值(根据 Donegative numbers return false in C/C++? - 码客)。

所以上面例子中的number里面有不同的项目总是会导致其中两个 lambda 函数返回true 也就是说,在这种情况下,那些 lambda 函数返回相同的结果。 但结果显示,一个是倒序的,一个是原序的。

我该如何解释这一点或我想念什么?

此处使用的比较函数无效。 如果 LHS 在预期的排序顺序中位于 RHS 之前,则传递给sort()的 function 应该返回 true,否则返回 false(即它应该表现得像“小于”)。 这里的 lambda 表达式都没有这样的行为,因此使用这些函数中的任何一个调用sort()都是未定义的行为。

在这两个调用中, sort()最终反转了它给出的顺序。 这只是一个意外, sort()碰巧在您的系统上实现的方式的意外随机副作用。 如果您尝试使用不同的编译器,您可能会得到不同的结果(例如崩溃)。

libstdc++ 中的std::sort实现针对短序列进行了优化,在检查了source之后,我们知道对于短于 16 个元素的小序列,它将退回到插入排序。

在 c++ 中,非零数可以自动转换为布尔值true ,使用插入排序,如果你的序列没有相同的值,它会被反转(在插入排序循环中,所有值都会被移动到第一位,然后一旦循环完成,序列就会恢复)。

这不是确定性行为,因为 STL 实现可能彼此不同,并且 _S_threshold 数字未向最终用户透露。

将数组扩大到超过 16 个元素,我们得到完全不同的结果:

程序因缓冲区溢出而崩溃! 所以现在我们证明使用这种类型的 lambda [](int n1, int n2) { return n2 - n1; }是错误的。 [](int n1, int n2) { return n2 - n1; } ,正确的方式应该是sort(begin(number), end(number), [](int n1, int n2) { return n2 > n1; });

#include <iostream> 
#include <functional>
#include <algorithm>
using namespace std; 

int main() { 
    int number[] = {3, 5, 1, 6, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
    auto print = [](int n) { cout << n << " "; };

    sort(begin(number), end(number), [](int n1, int n2) { return n2 - n1; });

    for_each(begin(number), end(number), print);
    cout << endl;

    sort(begin(number), end(number), [](int n1, int n2) { return n1 - n2; });

    for_each(begin(number), end(number), print);
    cout << endl;


    return 0; 
} 

n2 - n1在作为结果为负数的情况下转换为bool时将产生true 所以n1结果小于n2 这就是为什么在这种 Boolean 上下文中使用int是一种不好的做法

是的,如文档中所述:

...比较 function object 如果第一个参数小于第二个参数,则返回 true

但是这里比较的实现会导致失败。 试试这个,自己看看:

int x = 5, y = 555;
bool b = x - y;
std::cout << b << std::endl; // Prints 1, means true

提供的比较 function 必须遵循operator<的逻辑 所以,当你的 lambda 有n1 = 5, n2 = 1; n2 - n1的结果是-4在 Boolean 上下文中使用时( bool是无符号的)被转换为1

结果你有5 < 1 is true

虽然在您的 output 中 1 放在 5 之后,但这种错误比较会导致整体结果不理想。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM