为啥用于 stl 函数的 lambda 函数,如 C++ 中的 sort() 、 max_element() 函数需要两个参数作为输入?

Posted

技术标签:

【中文标题】为啥用于 stl 函数的 lambda 函数,如 C++ 中的 sort() 、 max_element() 函数需要两个参数作为输入?【英文标题】:Why does lambda function used for stl functions such as sort() , max_element() function in C++ take two arguments as input?为什么用于 stl 函数的 lambda 函数,如 C++ 中的 sort() 、 max_element() 函数需要两个参数作为输入? 【发布时间】:2017-12-15 01:09:11 【问题描述】:

我正在尝试了解 lambda 函数在 sort() 运算符中的使用。有一个向量存储person 类型的对象; sort() 函数用于迭代向量 person 并根据类成员 id 对其进行排序。

我不明白为什么排序函数中使用的 lambda 函数需要两个输入,即。 p1p2 ?,为什么不输入一个对象p1?我一直认为sort()max_element()等stl函数将迭代器返回到一个元素。

class Person
    
      private:
        string firstName;
        string lastName;
        int id;

      public:
        Person(const string& fn, const string& ln, int i)
             : firstName(fn), lastName(ln), id(i)  

        const string& getFirstName() const  return firstName; 
        const string& getLastName() const  return lastName; 
        int getID() const  return id; 
    ;

main()
vector<Person> people;
people.push_back(Person("Davor", "Loayza", 62341));
people.push_back(Person("Eva", "Lopez", 12345));
people.push_back(Person("Julio", "Sanchez", 54321));
people.push_back(Person("Adan", "Ramones", 70000));

sort(people.begin(), people.end(), [](const Person& p1, const Person& p2)

  return p1.getID() < p2.getID();
);
return 0;

编辑:可能我需要重申我的问题,我的问题是迭代器增量如何在sort() 函数中发生。最开始iterator = people.begin()时,p1赋值什么值,p2赋值什么值?同样,当 iterator=people.end() 时会发生什么?我很难理解这个过程背后的逻辑?

【问题讨论】:

lambda 不是成员函数,所以它不是从一个类调用的。 sort() 函数返回多少个迭代器? 排序函数不返回任何迭代器也许你的意思是别的? 您是在问为什么您的 lambda 函数需要采用p1p2 通常情况下,比较器函数,例如在您的代码 sn-p 中使用的,需要比较它们的两个东西。 【参考方案1】:

要了解std::sort,首先要了解什么是排序。这是一个适合你的练习:

给自己找一副纸牌。我将假设您知道哪张卡片的等级比较高于另一张卡片;否则这可能会令人困惑。 ace 的等级是否高于国王或低于 2 并不重要。你现在可以忽略西装。

将卡片排成一排(或扇形以节省空间)。目标是找出任何等级较高的卡是否在等级较低的卡之前。想想你怎么能找到它?

方法如下:从第一张卡片和第二张卡片开始。 比较他们的排名。第一张卡的等级比第二张高吗?如果是这样,我们得出结论,我们寻求的答案是“是的,有一张等级较高的牌在一张较低等级的牌之前”。如果第一张牌的等级不高于第二张,那么我们还不能回答这个问题。我们必须继续,将第二张卡片与第三张卡片进行比较,然后重复该过程。

如果你到达套牌的尽头时没有找到在低等级卡之前的高等级卡,那么我们寻求的答案是“否”。让我们称这种牌组为sorted(或ordered)。

第二个练习:如果这副牌没有排序,你怎么能把它排序?

方法如下:就像在第一个练习中一样,从前两张卡片开始。这一次,如果他们的顺序不理想,交换他们的位置,让拳头成为第二,第二成为第一。现在这两张卡按关系彼此排序。然后继续进行第二个和第三个并重复该过程。您会发现您可能需要多次重复此过程,因为一次迭代不一定足够。

让我们将此过程称为排序(更具体地说,这是比较排序)。这就是std::sort 所做的。它一次比较两个元素,并交换元素,直到任何相邻对之间的所有比较都为真,即直到对范围进行排序。

两张卡之间的比较类似于std::sort的比较函数对象参数所完成的比较步骤。如果您一次只看一张卡片,您将无法确定它是否在其有序位置。


为什么C++中sort()、max_element()等stl函数使用的lambda函数需要两个参数作为输入?

因为这些函数的比较函数对象参数表示迭代器范围的两个元素之间的顺序关系。顺序关系是二元关系。

为什么不只输入一个对象 p1?

因为一元关系不能代表顺序。

我一直认为像 sort() 和 max_element() 这样的 stl 函数将迭代器返回到一个元素。

sort() 函数返回多少个迭代器?

std::sort 根据文档返回void。也就是说,这些函数返回的内容与比较函数对象参数的数量关系不大。

我的问题是在 sort() 函数中迭代器增量是如何发生的

未指定。算法的实现者可以选择如何增加迭代器。排序算法通常使用多个迭代器。

一开始iterator = people.begin()的时候,p1被赋值了什么值,p2被赋值了什么值?

排序算法不必从范围的开头开始。不清楚你用iterator 指的是什么。

p1p2 将是[first, last) 范围内的一些对元素。究竟哪一对是由算法决定的。

【讨论】:

“因为一元关系不能代表一个顺序。” - 是的,它可以,通过投影到一个有序的范围内。 ;)【参考方案2】:

对容器中的元素调用 lambda 函数,以比较一个是否大于另一个。它不只是简单地调用一次以返回 sortsort 什么也不返回。它需要两个参数,因此它可以进行比较。如果它只接受一个参数,它将与什么进行比较?

【讨论】:

以上是关于为啥用于 stl 函数的 lambda 函数,如 C++ 中的 sort() 、 max_element() 函数需要两个参数作为输入?的主要内容,如果未能解决你的问题,请参考以下文章

C++ STL学习 —— 模板泛型算法函数对象lambda 表达式(参数捕获)函数适配器

C++ STL学习 —— 模板泛型算法函数对象lambda 表达式(参数捕获)函数适配器

C++中的()操作符重载及STL传递比较函数

lambda

为啥这个 stl 函数调用会导致不正确的布尔评估? [复制]

为啥我在使用 STL 列表时不能使用这个回文函数?