2010-11-01 151 views
15

在向量上使用STL排序算法时,我想传入我自己的比较函数,该函数也需要一个参数。将参数传递给比较函数?

例如,最好我想做一个本地函数声明,如:

int main() { 
    vector<int> v(100); 
    // initialize v with some random values 

    int paramA = 4; 

    bool comp(int i, int j) { 
     // logic uses paramA in some way... 
    } 

    sort(v.begin(), v.end(), comp); 
} 

然而,编译器会抱怨了一番。当我尝试类似:

int main() { 
    vector<int> v(100); 
    // initialize v with some random values 

    int paramA = 4; 

    struct Local { 
     static bool Compare(int i, int j) { 
      // logic uses paramA in some way... 
     } 
    }; 

    sort(v.begin(), v.end(), Local::Compare); 
} 

编译器仍然抱怨:“错误:使用参数从包含函数”

我应该怎么办?我应该使用全局比较函数来创建一些全局变量吗?

谢谢。

回答

22

您不能从本地定义的函数内访问函数的局部变量 - C++在其当前形式中不允许closures。该语言的下一个版本C++ 0x将支持这一点,但语言标准尚未最终确定,目前对草案标准的支持不多。

为了做到这一点,您应该将std::sort的第三个参数更改为对象实例而不是函数。 std::sort的第三个参数可以是任何可调用的(即,任何x,其中添加括号如x(y, z)使句法有意义)。要做到这一点,最好的方法是定义一个实现operator()功能的结构,然后传递对象的实例:

struct Local { 
    Local(int paramA) { this->paramA = paramA; } 
    bool operator() (int i, int j) { ... } 

    int paramA; 
}; 

sort(v.begin(), v.end(), Local(paramA)); 

请注意,我们必须存储paramA的结构,因为我们无法访问否则从operator()内。

+0

第三个参数是什么,可以使用函数调用语法来调用。因此,定义'operator()'的函数和类/结构都会起作用。 – 2010-11-01 04:17:46

+0

@Eugen:好点,我已经更新了我的回答以反映这一点。 – 2010-11-01 04:24:10

+0

谢谢,这是工作(除了编译器抱怨,除非我移动主函数以外的结构声明,我认为我们被允许本地声明类和结构..?) – George41 2010-11-01 04:39:42

10

在C++中,你不能在另一个函数中定义一个自由函数。所以你的第一个代码片段是不健康的。

sort(v.begin(), v.end(), Local::Compare);

第三个参数必须是一个函数对象。在类中重载()运算符,然后创建函数对象。


在C++ 0x中,您可以使用lambda expressions

auto comp = [&](int m,int n)-> bool { 

     return m<n; //or use paramA in some way 
    }; 

sort(v.begin(), v.end(), comp); 
+0

在我看来,由于使用漂亮的C++特性(lambda),这是一个比例外更好的解决方案, – Anonymous 2015-03-27 12:50:59

4

一种可能性是,当你建立你的比较对象来传递参数:

class cmp { 
    int param; 
public: 
    cmp(int p) : param(p) {} 

    bool operator()(int i, int j) { 
     // logic uses param 
    } 
}; 

int main() { 
    vector<int> v(100); 
    // initialize v with some random values 

    int paramA = 4; 

    sort(v.begin(), v.end(), cmp(paramA)); 
}