c++ - Was bedeutet es, dass Prädikate ihren Status aufgrund eines Funktionsaufrufs nicht ändern sollten?




c++11 stl (3)

Betrachten std::count_if als Beispiel den Algorithmus std::count_if . Es durchläuft einen Bereich und zählt, wie oft ein gegebenes Prädikat als wahr ausgewertet wird. Angenommen, wir möchten überprüfen, wie viele Elemente in einem Container kleiner als eine bestimmte Anzahl sind, z. B. 5 oder 15.

Ein Prädikat kann viele Dinge sein. Es muss nur aufrufbar sein. Es kann ein Funktor sein:

struct check_if_smaller {
    int x;
    bool operator()(int y) { return y < x; }
};

Sie können verschiedene Instanzen dieses Prädikats erstellen, z. B. diese beiden

check_if_smaller a{5};
check_if_smaller b{15};

kann verwendet werden, um zu überprüfen, ob die Zahlen kleiner als 5 bzw. 15 sind:

bool test1 = a(3);  // true because 3 < 5
bool test2 = b(20); // false because 20 is not < 15

Das Element x ist der Status des Prädikats. Normalerweise sollte sich dies nicht ändern, wenn das Prädikat angewendet wird (durch Aufrufen seines operator() ).

Aus wikipedia :

In der mathematischen Logik wird unter einem Prädikat üblicherweise eine Boolesche Funktion P: X → {wahr, falsch} verstanden, die als Prädikat für X bezeichnet wird. Prädikate haben jedoch viele verschiedene Verwendungen und Interpretationen in Mathematik und Logik sowie deren genaue Definition , Bedeutung und Verwendung variieren von Theorie zu Theorie.

Ein Prädikat ist eine Funktion, die etwas einem Booleschen Wert zuordnet. Die Tatsache, dass wir einen Funktor verwenden, der nicht nur eine Funktion, sondern ein Funktionsobjekt mit einem Status ist, kann als Implementierungsdetail betrachtet werden, und die wiederholte Auswertung desselben Prädikats für dieselbe Eingabe wird normalerweise zum gleichen Ergebnis führen. Algorithmen gehen von dieser Annahme aus und nichts hindert sie wirklich daran, das Prädikat, das Sie übergeben, zu kopieren. Wenn die Auswertung des Prädikats seinen internen Status ändern würde, funktioniert der Algorithmus möglicherweise nicht wie erwartet.

Ich habe online über C ++ gelesen und bin auf folgende Aussage gestoßen:

Prädikate sollten ihren Status aufgrund eines Funktionsaufrufs nicht ändern.

Ich habe nicht verstanden, was "Staat" hier bedeutet. Kann jemand bitte mit einem Beispiel ausarbeiten?


Im Wesentlichen sollte das Prädikat laut Standard (in mathematischen Begriffen) wie eine reine Funktion wirken, dh sein Rückgabewert sollte allein von der Eingabe abhängen.

Die Erwähnung des Status, weil Prädikate kopiert oder in verschiedenen Threads aufgerufen werden können, was von der Implementierung und dem Verhalten der Plattform abhängt. Für Lambdas und andere aufrufbare Objekte, die keine Funktionen sind, kann dies ungeordneten Zugriff auf den Speicher bedeuten, der als Referenz erfasst wurde, oder Zugriff auf andere Werte, wenn sie als Wert erfasst wurden. Für eine Funktion bedeutet dies, dass Nebenwirkungen (einschließlich der Änderung statischer Variablen) zu Problemen führen können.

Wenn ein Prädikat zum Sortieren unterschiedliche Ergebnisse für dasselbe Paar zurückgibt, werden einige Sortieralgorithmen ungültig.


Zusätzlich zu den anderen Antworten versprechen viele der Algorithmen, die Prädikate verwenden, keine bestimmte Durchquerungsreihenfolge (die ExecutionPolicy- Überladungen ermöglichen interleaved Traversal). Möglicherweise erhalten Sie unterschiedliche Antworten auf dieselbe Frage.

Wenn es mehrere Threads gibt, die 1 als Prädikat aufrufen und dabei einen gemeinsamen Wert ändern, handelt es sich um ein Datenrennen , dh ein undefiniertes Verhalten.

  1. oder ein Thread Interleaving-Aufrufe an




predicate