Frage

Es ist mir notwendig zu verwenden std::function Aber ich weiß nicht, was die folgende Syntax bedeutet.

std::function<void()> f_name = []() { FNAME(); };

Was ist das Ziel, zu verwenden? std::function? Ist es, einen Zeiger auf eine Funktion zu machen?

War es hilfreich?

Lösung

std::function ist ein Typ -Löschen -Objekt. Das bedeutet, dass es die Details der Einführung einiger Vorgänge auslöscht und ihnen eine einheitliche Laufzeitschnittstelle bietet. Zum std::function, die primäre1 Operationen sind Kopie/Bewegung, Zerstörung und "Aufruf" mit operator() - Die 'Funktion wie Anrufbetreiber'.

In weniger abstruse Englisch bedeutet das, dass das std::function Kann fast jedes Objekt enthalten, das wie ein Funktionszeiger in der Art und Weise wirkt, wie Sie es nennen.

Die Signatur, die es unterstützt, geht in die Winkelklammern: std::function<void()> Nimmt keine Argumente und gibt nichts zurück. std::function< double( int, int ) > nimmt zwei int Argumente und Rückgaben double. Im Algemeinen, std::function Unterstützt das Speichern eines funktionsähnlichen Objekts, dessen Argumente von seiner Argumentliste konvertiert werden können und deren Rückgabewert auf seinen Rückgabewert konvertiert werden kann.

Es ist wichtig zu wissen std::function und Lambdas sind unterschiedlich, wenn auch kompatibel, Bestien.

Der nächste Teil der Linie ist ein Lambda. Dies ist eine neue Syntax in C ++ 11, um die Möglichkeit hinzuzufügen, einfache funktionsähnliche Objekte zu schreiben-Objekte, die aufgerufen werden können (). Solche Objekte können in a gelöscht und gespeichert werden std::function Auf Kosten einiger Laufzeit über Kopf.

[](){ code } Insbesondere ist ein wirklich einfaches Lambda. Es entspricht dem:

struct some_anonymous_type {
  some_anonymous_type() {}
  void operator()const{
    code
  }
};

Eine Instanz des obigen einfachen Pseudo-Funktionstyps. Eine tatsächliche Klasse wie die oben genannte wird vom Compiler mit einem implementierenden eindeutigen Namen "erfunden" (oft einschließlich Symbole, die kein benutzerdefinierter Typ enthalten kann) (ich weiß nicht, ob es möglich ist, dass Sie dem Standard ohne Erfindung folgen können Eine solche Klasse, aber jeder Compiler, von dem ich kenne, erstellt tatsächlich die Klasse).

Die volle Lambda -Syntax sieht aus wie:

[ capture_list ]( argument_list )
-> return_type optional_mutable
{
  code
}

Aber viele Teile können weggelassen oder leer gelassen werden. Die Capture_List entspricht sowohl dem Konstruktor des resultierenden anonymen Typs als auch seinen Mitgliedsvariablen, das Argument_List die Argumente der operator(), und der Rückgabetyp den Rückgabetyp. Der Konstruktor der Lambda -Instanz wird auch auf magische Weise auf magische Weise aufgerufen, wenn die Instanz mit der Capture_List erstellt wird.

[ capture_list ]( argument_list ) -> return_type { code }

im Grunde wird

struct some_anonymous_type {
  // capture_list turned into member variables
  some_anonymous_type( /* capture_list turned into arguments */ ):
    /* member variables initialized */
  {}
  return_type operator()( argument_list ) const {
    code
  }
};

Beachten Sie das in Vorlagenargumente wurden zu Lambdas hinzugefügt, und das ist nicht oben nicht behandelt.

[]<typename T>( std::vector<T> const& v ) { return v.size(); }

1 Darüber hinaus wird RTTI gespeichert (Typid) und der Operation vom Typ Cast-Back-to-Original ist enthalten.

Andere Tipps

Lassen Sie uns die Linie auseinander brechen:

STD :: Funktion

Dies ist eine Erklärung für eine Funktion, die keine Parameter enthält und keinen Wert zurückgibt. Wenn die Funktion eine zurückgegeben hat int, es würde so aussehen:

std::function<int()>

Ebenso, wenn es auch einen INT -Parameter benötigte:

std::function<int(int)>

Ich vermute, Ihre Hauptverwirrung ist der nächste Teil.

[]() { FNAME(); };

Das [] Teil heißt a Erfassungsklausel. Hier setzen Sie Variablen ein, die lokal in die Erklärung Ihres Lambda sind und Sie verfügbar sein möchten innerhalb Die Lambda -Funktion selbst. Das heißt: "Ich möchte, dass nichts gefangen genommen wird". Wenn dies innerhalb einer Klassendefinition lag und Sie wollten, dass die Klasse der Lambda zur Verfügung steht, können Sie dies tun:

[this]() { FNAME(); };

Der nächste Teil ist die Parameter, die an die Lambda übergeben werden. Genau das gleiche, als wäre es eine reguläre Funktion. Wie bereits erwähnt, std::function<void()> Zeigt eine Signatur auf eine Methode, die keine Parameter annimmt, so dass dies auch leer ist.

Der Rest ist der Körper der Lambda selbst, als wäre es eine reguläre Funktion, die wir sehen können, die nur die Funktion aufruft FNAME.

Ein anderes Beispiel

Nehmen wir an, Sie hatten die folgende Unterschrift, dh für etwas, das zwei Zahlen zusammenfassen kann.

std::function<int(int, int)> sumFunc;

Wir könnten jetzt ein Lambda so erklären:

sumFunc = [](int a, int b) { return a + b; };

Ich bin mir nicht sicher, ob Sie MSVC verwenden, aber hier ist sowieso ein Link zur Lamda -Expressionssyntax:

http://msdn.microsoft.com/en-us/library/dd293603.aspx

Lambdas mit Erfassungen (staatlich Lambdas) können nicht einander zugeordnet werden, da sie einzigartige Typen haben, auch wenn sie genau gleich aussehen. Um Lambdas mit Erfassungen zu lagern und zu passieren, können wir verwenden. "STD :: Funktion"Um ein Funktionsobjekt zu halten, das durch einen Lambda -Ausdruck konstruiert ist. Grundsätzlich"STD :: Funktion"Ist es in der Lage, Lambda -Funktionen mit unterschiedlichen Inhaltsstrukturen einem Lambda -Funktionsobjekt zuweisen zu können.

Exp:

auto func = [](int a){
 cout << "a:" << a << endl;
};
func(40);
//
int x = 10;
func = [x](int a){ //ATTENTION(ERROR!): assigning a new structure to the same object
 cout << "x:" << x << ",a:" << a << endl;
};
func(2);

Die obige Verwendung ist also falsch. Aber wenn wir ein Funktionsobjekt mit "std :: function" definieren:

auto func = std::function<void(int)>{};
func = [](int a){
  cout << "a:" << a << endl;
};
func(40);
//
int x = 10;
func = [x](int a){ //CORRECT. because of std::function
  //...
}; 

int y = 11;
func = [x,y](int a){ //CORRECT
 //...
}; 
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top