2010-12-14 5 views
7

Ich habe eine Liste von MyClass:Welcher Fall ist besser?

struct MyClass { 
    bool is_old_result(int lifetime); 
}; 
std::list<MyClass> results; 
int lifetime = 50; // or something else 

Was Fall besser ist das Entfernen (C++ Design und perfomance):

results.remove_if(
    std::bind2nd(std::mem_fun_ref(&MyClass::is_old_result), lifetime)); 

oder

results.remove_if(boost::bind(&MyClass::is_old_result, _1, lifetime)); 

oder

struct RemoveFunctor { 
    RemoveFunctor (int lifetime) : lifetime(lifetime) {} 
    bool operator()(const MyClass & m) { return m.is_old_result(lifetime); } 
private: 
    int lifetime; 
}; 
results.remove_if(RemoveFunctor(lifetime)); 

und warum?

P.S. Bitte, keine Lambda-Funktion und kein C++ 0x.

Antwort

12

In Bezug auf das Design ist das mit bind definitiv am klarsten. (gefolgt vom expliziten Funktionsobjekt). Warum? Prägnant.

In Bezug auf die Leistung sollte das Funktionsobjekt unschlagbar sein (alles kann einfach analysiert und inline) werden. Abhängig davon, wie der Compiler optimiert, könnte der, der bind verwendet, möglicherweise damit übereinstimmen (der Aufruf an is_old_result kann oder kann nicht durch einen Zeiger erfolgen, abhängig von der Analyse des Compilers).

+0

stimme ich vollständig zu. – ltjax

+0

Ich stimme zu, die Bind-Syntax ist am einfachsten zu lesen. Wenn Leistung eine zweitrangige Angelegenheit ist, gehen Sie mit Bind hier. –

+3

Ich stimme dem auch zu, und ich möchte hinzufügen, dass die Leistung nur zweitrangig sein sollte, es sei denn, Sie haben ein Profil erstellt und festgestellt, dass diese Aussage ein Leistungsengpass ist. –

3

Mit geeigneter Namensgebung wie „IsOldResult“ oder „ResultOlderThan“, würde ich sagen, dass die endgültige Lösung der meisten lesbar sein würde, wie es derjenige ist, der am meisten für Prosa geht:

results.remove_if(ResultOlderThan(lifetime)); 

Allerdings würde ich wahrscheinlich nur den Funktor schreiben, wenn der Algorithmus, den er repräsentiert, in mehreren Kontexten auftaucht. Eine 5-Zeilen-Klasse zu schreiben, die physisch von ihrer einzigen Ein-Liner-Call-Site entfernt ist, erscheint mir zu verschwenderisch.

Sonst hat die boost :: bind Option meine Stimme, da sie die geringste zusätzliche Flaum zwischen ihr und std :: bind2nd (_1 bzw. std :: mem_fun_ref) hat. Darüber hinaus arbeitet boost :: bind im Allgemeinen für mehrere Fälle, beispielsweise wenn Sie nur eine Variable einer Funktion binden, die nur zwei Parameter hat.

+0

guter Punkt über geeignete 'ResultOlderThan' –