Sollte ich Funktionen oder statuslose Funktoren verwenden?

8

Diese 2 Teile Code machen dasselbe. Und es wird in der Sortierfunktion verwendet, wie Sie sehen können. Welches ist besser? Normalerweise schreibe ich Letzteres. Aber ich habe einige Programmierer gesehen, die es wie früher gemacht haben.

%Vor%

und

%Vor%

Verwendet es wie:

%Vor%     
Josh Morrison 02.04.2011, 07:41
quelle

6 Antworten

5

Der erste wird als Funktionsobjekt bezeichnet und ist nützlich, wenn Sie der Vergleichsfunktion eine beliebige Kontextinformation übergeben müssen. Die Standalone-Funktion ruft nur x und y ab und hat nicht die Möglichkeit, irgendeinen Kontext mitzunehmen.

Im obigen Beispiel sind die beiden Schreibweisen der Vergleichsfunktion ungefähr gleich.

    
Greg Hewgill 02.04.2011 07:44
quelle
4

Der Grund, warum einige Leute die erste Version bevorzugen, ist, dass Funktogramme trivial inline sein können.

Wenn Sie einen Funktor an std::sort übergeben, ist der Funktortyp der Funktion bekannt. Daher ist die genaue Funktion zum Aufrufen auch zur Kompilierungszeit bekannt und kann trivial inline sein.

Mit einer einfachen Funktion sieht std::sort wirklich nur einen Funktionszeiger und zur Kompilierungszeit nichts über welche Funktion darauf hinweist. Dies kann nicht inline gemacht werden, es sei denn, der Compiler führt eine ziemlich umfangreiche Flussanalyse durch, um zu sehen, wo der Zeiger von in diesem spezifischen Aufruf kam . Und es wird sicherlich diese Optimierung in einem kleinen Beispiel wie deins tun, aber wenn der Funktor / Funktionszeiger beispielsweise von einer anderen Stelle als Funktionsargument übergeben wurde oder aus einer Zwischendatenstruktur gelesen wurde, bevor er an% co_de übergeben wurde %, dann ist der Compiler möglicherweise nicht in der Lage, die Funktionszeigerversion einzubinden, und so würde es langsamer enden.

    
jalf 02.04.2011 08:51
quelle
1

Ich würde wahrscheinlich die erste in der Regel bevorzugen, würde aber im Allgemeinen eine Vorlage bevorzugen:

%Vor%

Die Verwendung von .second begrenzt den Grad der Generizität, aber Sie erhalten immer noch ein wenig (zB, wenn Speicher dient, liefert boost::tuple eine .first und .second für Tupel von zwei Elementen. In der Regel sein Eine Vorlage gibt ein wenig bessere Sicherheit, dass der Compiler in der Lage ist, den Code inline zu generieren. Wenn Sie also auf Effizienz achten, kann das ein wenig helfen (oder auch nicht, aber es ist unwahrscheinlich, dass es jemals Schaden anrichtet).

>     
Jerry Coffin 02.04.2011 07:46
quelle
1

Wenn Sie auch die Funktion in einem anderen Teil Ihres Codes aufrufen und nicht als Funktor übergeben möchten, bevorzugen Sie das Funktionsformular. Zum Beispiel würden Sie bevorzugen:

%Vor%

bis

%Vor%

Wenn Sie das Funktorformular auswählen, rufen Sie besser ein unbenanntes Funktorobjekt auf. Das ist:

%Vor%

anstelle von:

%Vor%

Das Auflisten von Parametern und Rückgabewerten ermöglicht dem Compiler die Optimierung. Es bezieht sich auf ein globales Konzept, das als RVO (Return Value Optimization) bekannt ist. In diesem Fall wird es wahrscheinlich Ihren Code von einer Kopie befreien.

    
yves Baumes 02.04.2011 08:41
quelle
0

Ich würde sagen, wählen Sie die einfachste, die für Ihren speziellen Fall funktioniert. In diesem Fall wählen Sie die zweite über die erste.

    
Lie Ryan 02.04.2011 08:40
quelle
-2

Beide werden gleich schnell sein. Fast vernachlässigbarer Unterschied.

Wenn Sie functor verwenden, bedeutet dies, dass die Funktion operator() drei Parameter im vom Compiler erzeugten Code hat, der erste Parameter ein Zeiger auf das val_lt -Objekt selbst ist und der zweite und dritte Parameter die Parameter, die Sie haben Habe in der Unterschrift erwähnt. Etwas wie das:

%Vor%     
Nawaz 02.04.2011 07:46
quelle

Tags und Links