繁体   English   中英

std的目的:在调用<运算符时少(或类似函数)

[英]Purpose of having std:less (or similar function) while it just call < operator

为什么std::less (和等效的其他函数对象)只需要调用<运算符,我们可以反过来运算符?

可能的答案有问题:

为什么std ::比“<”更好?

但是我并不完全相信(特别是关于弱排序)。 有人可以解释一下吗?

std::less和friends的目的是它允许你概括你的代码。 让我们说我们正在编写一个排序函数。 我们一开始

void sort(int * begin, int * end) { /* sort here using < /* }

所以现在我们可以对我们可以获得int*的容器进行排序。 现在让我们把它变成一个模板,这样它就适用于所有类型

template<typename Iterator>
void sort(Iterator begin, Iterator end) { /* sort here using < /* }

现在我们可以对任何类型进行排序,并且我们使用“迭代器”作为我们说我们需要指向元素的东西的方式。 这一切都很好但是这意味着我们需要传递任何类型来提供operator <使其工作。 它也不允许使用更改排序顺序。

现在我们可以使用函数指针,但这对内置类型不起作用,因为没有可以指向的函数。 如果我们改为创建一个额外的模板参数,让我们称之为Cmp ,那么我们可以在Cmp类型的函数中添加另一个参数。 这将是比较功能。 我们想为此提供一个默认值,因此使用std::less可以很容易地为我们提供良好的“默认”行为。

有这样的东西

template<typename Iterator, typename Cmp>
void sort(Iterator begin, Iterator end, 
          Cmp c = std::less<typename std::iterator_traits<Iterator>::value_type>) 
          { /* sort here using c /* } 

它允许您对所有内置类型(具有operator <任何类型)进行排序,并允许您指定任何其他方式来比较数据中的元素以对其进行排序。

这就是为什么我们需要std::less和朋友。 它让我们使代码通用和灵活,而无需编写大量的锅炉板。


使用函数对象也为我们带来了一些性能优势。 如果使用函数指针,编译器更容易内联对函数调用操作符的调用。 它还允许比较器具有状态,就像它被调用的次数一样。 有关此内容的更深入了解,请参阅C ++ Functors及其用法

std::less只是一个默认策略,它采用对象的自然排序顺序(即其比较运算符)。

使用std::less作为默认模板参数的好处是,您可以调整排序算法(或您的有序数据结构),以便您可以决定是否使用自然排序顺序(例如,自然排序的次要到主要)或针对您的特定问题的不同排序顺序(例如,第一个奇数,然后是偶数),而无需修改实际对象运算符或算法本身。

struct natural {
   unsigned value;

   natural( unsigned v ) :
     value(v)
   {
   }

   bool operator< ( natural other ) const {
      return value < other.value;
   }
};

struct first_the_odds {
   bool operator()( natural left, natural right ) const {
      bool left_odd  = left.value % 2 != 0;
      bool right_odd = right.value % 2 != 0;

      if( left_odd == right_odd ) {
         return left < right;
      } else {
         return left_odd;
      }
   }
};

// Sort me some numbers
std::vector<natural> numbers = { 0, 1, 2, 3, 4 };
std::sort( numbers.begin(), numbers.end(), first_the_odds() );
for( natural n : numbers )
   std::cout << n.value << ",";

输出:

1, 3, 0, 2, 4,

<的第一个问题是,在C ++标准下, < on pointers对于任何不指向同一“父”对象或数组的东西都是完全无稽之谈。

这是因为存在分段存储模型,如8086。 通过忽略段号在段内进行比较要快得多,并且对象不能跨越段; 所以<只能比较段内的偏移量并忽略段号。

在同样奇怪的硬件上还会出现这样的其他情况; 想象一下硬件,其中const(ROM)和非const(RAM)数据存在于一个单独的存储空间中。

std::less<Pointer>同时保证了严格的弱排序,尽管内存架构中存在任何怪癖。 它将为每次比较付出代价。

我们需要std::less的第二个原因是能够在easiliy周围传递“小于”的概念。 看看std::sort的3参数重载:

void sort( Iterator, Iterator, Comparator )

在这里我们可以传递我们想要在第3个参数中排序的方式。 如果我们传递std::greater<Foo>{}我们得到一种,如果我们传递std::less<Foo>{}我们会得到相反的结果。

默认情况下,2参数版本的排序类似于std::less ,但是一旦你有更大,更大的相等,更少相等,添加更少只是有意义。

一旦你定义了更少,用它来描述默认std sort和std map之类的行为比重复所有关于它如何使用的措辞更容易<除非它是在指针上然后它产生严格的弱排序同意< where <在标准中有完全指定的行为。

暂无
暂无

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

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