【问题标题】:Use STL std::sort the way as qsort_r使用 STL std::sort 作为 qsort_r
【发布时间】:2014-12-29 02:46:13
【问题描述】:

通过qsort_r,我们可以在比较函数中使用外部参数。例如,

int cmp_with_parameter(void *a, void *b, void *p) 
{
  return (int*)p[*(int*)a] - (int*)p[*(int*b)];
}

int main() {
  int values[] = {1,2,3,4};
  int arr[] = {0, 1, 2, 3};
  qsort_r(arr, 4, sizeof(arr[0]), cmp_with_parameter, values);
}

我们可以按照values[]中的值对int arr[]进行排序。

现在,我想用 std::sort 实现类似的功能,这就是我如何在 std::sort 中使用外部值?先感谢您。

【问题讨论】:

  • 阅读函子和/或匿名函数对象(或“lambdas”)。
  • 通过引用或其他方便的方式将参数加载到自定义比较器中。

标签: c++ c sorting stl


【解决方案1】:

std::sort()所采用的比较函数可以是一个函数对象,它保存着合适的信息。例如:

std::sort(std::begin(arr), std::end(arr),
          [=](int a, int b){ return values[a] < values[b]; });

【讨论】:

  • 谢谢,它有效。也许我应该在 lambda 表达式中通过引用传递:)
  • @OphirGvirtzer:为什么?数组肯定会像往常一样衰减并捕获指针。鉴于数组是不可复制的,我看不出它的工作方式有何不同。
  • 是的,当数组是指针时,我们不需要引用。我在另一个地方使用了 vector 。我对此感到抱歉。谢谢:)
  • Dietmar - 是的,你是对的。但是 [=] 语法让我害怕。如果有人将数组更改为 std::array 或 std::vector 怎么办?他会注意到问题并更改 lambda 捕获吗?我永远不会使用 [=],而是明确指定要按值捕获的每个变量。
【解决方案2】:

你需要创建一个 functor 作为你的比较器。制作 functor 的常用方法是使用 struct 并重载调用运算符:

struct cmp_with_parameter
{
    const int* values; // keep a pointer to the external array

    cmp_with_parameter(const int* values): values(values) {}

    // overloading this operator allows an object
    // of this struct to be called like a function.
    bool operator()(int a, int b) const
    {
        return values[a] < values[b];
    }
};

int main()
{
    int values[] = { 1, 2, 3, 4 };
    int arr[] = { 0, 1, 2, 3 };
    std::sort(arr, arr + sizeof(arr)/sizeof(arr[0]), cmp_with_parameter(values));

    // ...
}

如果你的编译器支持C++11,你可以简化std::sort()参数:

int main()
{
    int values[] = { 1, 2, 3, 4 };
    int arr[] = { 0, 1, 2, 3 };
    std::sort(std::begin(arr), std::end(arr), cmp_with_parameter(values));

    // ...
}

维基百科有一个很好的例子来说明如何解决这个问题:Function Object:C/C++

【讨论】:

  • 找出结束迭代器的方法可以得到显着改进,不过:std::sort(std::begin(arr), std::end(arr), cmp_with_parameters(values))
  • @DietmarKühl 谢谢,我将它保留在 C++11 之前,但我会将您的建议添加为有用的注释。
  • 好吧,C++11 已经过时,而 C++14 是当前的标准。为什么有人会想考虑 C++11 之前的版本,这有点超出我的理解(尽管我意识到公司可能对所使用的 C++ 版本有限制)。 ...即使使用 C++98,一个简单的 end() 函数也可以确定数组的大小。
  • @DietmarKühl 只是问题没有指定 C++11,我看到很多提问者说他​​们无法使用它。但我同意 pre C++11 已经过时了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-03
  • 1970-01-01
  • 2021-06-03
相关资源
最近更新 更多