Heute habe ich über reine Funktion gelesen und war verwirrt mit ihrer Verwendung:
Eine Funktion gilt als rein, wenn sie denselben Wertesatz für denselben Eingangssatz zurückgibt und keine beobachtbaren Nebenwirkungen aufweist.
zB strlen()
ist eine reine Funktion, während rand()
es eine unreine ist.
__attribute__ ((pure)) int fun(int i)
{
return i*i;
}
int main()
{
int i=10;
printf("%d",fun(i));//outputs 100
return 0;
}
Das obige Programm verhält sich genauso wie ohne pure
Deklaration.
Was sind die Vorteile der Deklaration einer Funktion als pure
[wenn sich die Ausgabe nicht ändert]?
c
pure-virtual
Grüner Kobold
quelle
quelle
printf
zum Beispiel würde sie sich qualifizieren (zweimal mit denselben Argumenten aufzurufen, ergibt denselben Rückgabewert), aber sie ist nicht rein....and no side-effects...
Teil.Antworten:
pure
Lässt den Compiler wissen, dass er bestimmte Optimierungen an der Funktion vornehmen kann: Stellen Sie sich ein bisschen Code vorMit einer reinen Funktion kann der Compiler wissen, dass er
fun(10)
nur einmal und nicht 1000-mal auswerten muss . Für eine komplexe Funktion ist das ein großer Gewinn.quelle
strlen
es an. Dann wieder. Gleiches ja? Ändern Sie nun das zweite Zeichen\0
. Gibtstrlen
jetzt noch 1000 zurück? Die Startadresse ist dieselbe (== Eingabe ist dieselbe), aber die Funktion gibt jetzt einen anderen Wert zurück.strlen
(in GCC / glibc) tatsächlich rein ist. Ein Blick auf die glibc-Implementierung hat jedoch gezeigt, dass dies falsch ist.Wenn Sie sagen, dass eine Funktion "rein" ist, garantieren Sie, dass sie keine äußerlich sichtbaren Nebenwirkungen hat (und wie ein Kommentar sagt, wenn Sie lügen, können schlimme Dinge passieren). Zu wissen, dass eine Funktion 'rein' ist, hat Vorteile für den Compiler, der dieses Wissen nutzen kann, um bestimmte Optimierungen vorzunehmen.
In der GCC-Dokumentation steht Folgendes zu dem
pure
Attribut:Die Antwort von Philip zeigt bereits, wie das Wissen, dass eine Funktion "rein" ist, bei Schleifenoptimierungen helfen kann.
Hier ist eine für die gemeinsame Eliminierung von Subausdrücken (angegeben
foo
ist rein):Kann werden:
quelle
call
Anweisung einen Engpass für superskalare CPUs darstellt, kann eine Hilfe des Compilers hilfreich sein.foo
es Teil einer anderen Kompilierungseinheit (einer anderen C-Datei) oder in einer vorkompilierten Bibliothek ist. In beiden Fällen weiß der Compiler nicht, was erfoo
tut, und kann nicht vorberechnen.Zusätzlich zu den möglichen Laufzeitvorteilen ist eine reine Funktion beim Lesen von Code viel einfacher zu überlegen. Darüber hinaus ist es viel einfacher, eine reine Funktion zu testen, da Sie wissen, dass der Rückgabewert nur von den Werten der Parameter abhängt.
quelle
Eine nicht reine Funktion
ist wie eine Erweiterung einer reinen Funktion
in dem Sie neben den expliziten Funktionsargumenten x, y den Rest des Universums (oder alles, mit dem Ihr Computer kommunizieren kann) als implizite potenzielle Eingabe haben. Ebenso ist neben dem expliziten ganzzahligen Rückgabewert alles, worauf Ihr Computer schreiben kann, implizit Teil des Rückgabewerts.
Es sollte klar sein, warum es viel einfacher ist, über eine reine Funktion nachzudenken als über eine nicht reine.
quelle
Nur als Add-On möchte ich erwähnen, dass C ++ 11 die Dinge mit dem Schlüsselwort constexpr etwas codiert. Beispiel:
Die Einschränkungen bei der Verwendung von constexpr machen es so, dass die Funktion nachweislich rein ist. Auf diese Weise kann der Compiler aggressiver optimieren (stellen Sie bitte sicher, dass Sie die Schwanzrekursion verwenden!) Und die Funktion zur Kompilierungszeit anstatt zur Laufzeit auswerten.
Um Ihre Frage zu beantworten: Wenn Sie C ++ verwenden (ich weiß, dass Sie C gesagt haben, aber sie sind verwandt), ermöglicht das Schreiben einer reinen Funktion im richtigen Stil dem Compiler, alle möglichen coolen Dinge mit der Funktion zu tun: -)
quelle
Im Allgemeinen haben Pure-Funktionen drei Vorteile gegenüber unreinen Funktionen, die der Compiler nutzen kann:
Caching
Nehmen wir an, Sie haben eine reine Funktion
f
, die 100000 Mal aufgerufen wird. Da sie deterministisch ist und nur von ihren Parametern abhängt, kann der Compiler ihren Wert einmal berechnen und bei Bedarf verwendenParallelität
Reine Funktionen lesen oder schreiben nicht in einen gemeinsam genutzten Speicher und können daher ohne unerwartete Konsequenzen in separaten Threads ausgeführt werden
Referenzübergabe
Eine Funktion
f(struct t)
erhält ihr Argumentt
nach Wert, und andererseits kann der Compilert
unter Bezugnahme darauf übergeben,f
ob sie als rein deklariert ist, und gleichzeitig sicherstellen, dass sich der Wert vont
nicht ändert und Leistungssteigerungen erzieltZusätzlich zu den Überlegungen zur Kompilierungszeit können reine Funktionen ziemlich einfach getestet werden: Rufen Sie sie einfach auf.
Sie müssen keine Objekte erstellen oder Verbindungen zu DBs / Dateisystemen herstellen.
quelle