问题sorting使用成员函数作为比较
试图编译下面的代码我得到这个编译错误,我能做什么?
ISO C ++禁止采用非限定或带括号的非静态成员函数的地址来形成指向成员函数的指针。
class MyClass { int * arr; // other member variables MyClass() { arr = new int[someSize]; } doCompare( const int & i1, const int & i2 ) { // use some member variables } doSort() { std::sort(arr,arr+someSize, &doCompare); } };
doCompare
必须是static
。 如果doCompare
需要MyClass
数据,则可以通过更改以下命令将MyClass
转换为比较doCompare
函数:
doCompare( const int & i1, const int & i2 ) { // use some member variables }
成
bool operator () ( const int & i1, const int & i2 ) { // use some member variables }
并呼吁:
doSort() { std::sort(arr,arr+someSize, *this); }
另外,是不是doSort
缺less一个返回值?
我认为应该可以使用std::mem_fun
和某种绑定来将成员函数转换为一个自由函数,但是确切的语法在此刻回避了我。
编辑:嘿, std::sort
需要函数的价值,这可能是一个问题。 为了解决这个问题,在课堂上包装了函子:
class MyClass { struct Less { Less(const MyClass& c) : myClass(c) {} bool operator () ( const int & i1, const int & i2 ) {// use 'myClass'} MyClass& myClass; }; doSort() { std::sort(arr,arr+someSize, Less(*this)); } }
正如Andreas Brinck所说,doCompare必须是静态的(+1)。 如果你必须在你的比较函数中使用一个状态(使用类的其他成员),那么你最好使用一个函数而不是函数(这将更快):
class MyClass{ // ... struct doCompare { doCompare( const MyClass& info ) : m_info(info) { } // only if you really need the object state const MyClass& m_info; bool operator()( const int & i1, const int & i2 ) { // comparison code using m_info } }; doSort() { std::sort( arr, arr+someSize, doCompare(*this) ); } };
使用仿函数总是更好,只要input更长的时间(这可能是不方便的,但哦…)
我想你也可以使用std :: bind与成员函数,但我不知道如何也不会很容易阅读。
更新2014年:今天我们可以访问c ++ 11编译器,所以你可以使用lambda代码,代码会更短,但具有完全相同的语义。
你可以使用boost::bind
:
void doSort() { std::sort(arr,arr+someSize, boost::bind(&MyClass::doCompare, this, _1, _2)); }
Rob提出的解决scheme现在是有效的C ++ 11(不需要Boost):
void doSort() { using namespace std::placeholders; std::sort(arr, arr+someSize, std::bind(&MyClass::doCompare, this, _1, _2)); }
事实上,正如Klaim所提到的,lambda是一个选项,有点冗长(你必须“重复”参数是整数):
void doSort() { using namespace std::placeholders; std::sort(arr, arr+someSize, [this](int l, int r) {return doCompare(l, r); }); }
C ++ 14在这里支持auto
:
void doSort() { using namespace std::placeholders; std::sort(arr, arr+someSize, [this](auto l, auto r) {return doCompare(l, r); }); }
但是,您仍然声明参数是通过复制传递的。
那么问题是“哪一个最有效率”。 Travis Gockel对待这个问题: Lambda vs Bind 。 他的基准testing程序在我的电脑上(OS X i7)
Clang 3.5 GCC 4.9 lambda 1001 7000 bind 3716166405 2530142000 bound lambda 2438421993 1700834000 boost bind 2925777511 2529615000 boost bound lambda 2420710412 1683458000
lambda
是直接使用的lambda, lambda bound
是一个存储在std::function
的lambda。
所以看来lambda是一个更好的select,因为编译器提供了更高级别的信息,从中获利,这并不太令人意外。
有办法做你想做的,但你需要使用一个小的适配器。 由于STL不会为你写,所以你可以自己写:
template <class Base, class T> struct adaptor_t { typedef bool (Base::*method_t)(const T& t1, const T& t2)); adaptor_t(Base* b, method_t m) : base(b), method(m) {} adaptor_t(const adaptor_t& copy) : base(copy.base), method(copy.method) {} bool operator()(const T& t1, const T& t2) const { return (base->*method)(t1, t2); } Base *base; method_t method; } template <class Base, class T> adaptor_t<Base,T> adapt_method(Base* b, typename adaptor_t<Base,T>::method_t m) { return adaptor_t<Base,T>(b,m); }
那么,你可以使用它:
doSort() { std::sort(arr,arr+someSize, adapt_method(this, &doCompare)); }
有效使用成员函数的一个非常简单的方法是使用operator <。 也就是说,如果你有一个叫做compare的函数,你可以从operator <来调用它。 这是一个工作的例子:
class Qaz { public: Qaz(int aX): x(aX) { } bool operator<(const Qaz& aOther) const { return compare(*this,aOther); } static bool compare(const Qaz& aP,const Qaz& aQ) { return aP.x < aQ.x; } int x; };
那么你甚至不需要把函数名称给std :: sort:
std::vector<Qaz> q; q.emplace_back(8); q.emplace_back(1); q.emplace_back(4); q.emplace_back(7); q.emplace_back(6); q.emplace_back(0); q.emplace_back(3); std::sort(q.begin(),q.end());
更新Graham Asher的答案,因为你不需要比较,但可以直接使用less运算符。
#include <iostream> #include <vector> #include <algorithm> using namespace std; class Qaz { public: Qaz(int aX): x(aX) { } bool operator<(const Qaz& aOther) const { return x < aOther.x; } int x; }; int main() { std::vector<Qaz> q; q.emplace_back(8); q.emplace_back(1); q.emplace_back(4); q.emplace_back(7); q.emplace_back(6); q.emplace_back(0); q.emplace_back(3); std::sort(q.begin(),q.end()); for (auto& num : q) std::cout << num.x << "\n"; char c; std::cin >> c; return 0; }
- 在C#4.0中命名参数和genericstypes推断
- 模板问题导致链接器错误(C ++)
- Xcode显示了许多错误,但程序编译和运行良好(在模拟器和设备)
- 编译错误 – 在共享主机上编译git时找不到msgfmt命令
- Swift编译器错误:string连接上的“expression式太复杂”
- 无法打开输出文件,权限被拒绝
- 错误:安装脚本退出错误:命令“x86_64-linux-gnu-gcc”失败,退出状态为1
- 不能将types'System.Collections.Generic.IEnumerable <AnonymousType#1>'隐式转换为'System.Collections.Generic.List <string>
- 为什么这个程序被三个C ++编译器错误地拒绝?