In Python musste ich Werte von zwei Variablen austauschen, alles was Sie tun mussten, war
%Vor%Man kann es so betrachten, als ob die beiden Anweisungen (x = y) und (y = x) parallel und nicht nacheinander ausgeführt werden.
Gibt es eine Möglichkeit, den gleichen Effekt in C ++ zu erreichen?
HINWEIS / BEARBEITEN:
Ich möchte diesen "Paralleleffekt" (falls vorhanden) auf kompliziertere Ausdrücke wie
ones,twos= (ones ^ n) ^ ~twos, (ones & n) | (twos & ~n);
Das ist in Python möglich, ist das in C ++ möglich?
SCHLUSSFOLGERUNG:
Also laut der Antwort von leemes und den Kommentaren zu seiner Antwort:
1.Sie können Boost-Bibliotheken in C ++ 03 oder
verwenden2. Sie können C ++ 11
verwenden, um auf die std::tie
und std::tuple
zuzugreifen, um diesen "parallelen" Effekt zu erzielen.
Was die Gegenwart betrifft, markiere ich leemes als akzeptiert, aber ich werde immer noch nach Methoden suchen, um diese coole Funktionalität in C ++ 03 zu implementieren.
Sonderfall: Tauschen Sie den Wert von zwei Variablen
(Für die allgemeine Lösung, siehe unten.)
Um die Werte zweier Variablen in C ++ zu vertauschen, sollten Sie immer swap
verwenden:
Stört nicht wie es es tun wird; es wird es sehr schnell machen. Die Implementierung der C ++ - Standardbibliothek wird ihr Bestes tun, um dies zu einem einzelnen Befehl zu optimieren, wenn der Prozessor dies unterstützt (aber der Standard teilt der Implementierung dies nicht mit). Für Register-Only-Variablen gibt es zum Beispiel die x86-Anweisung xchg
, die das genauso schnell macht wie möglich. Versuchen Sie nicht, es mit einigen "drei XOR-Operationen" zu optimieren, es wird nicht schneller sein. Wenn Sie Pech haben, wird es nicht für so etwas wie xchg
optimiert.
Die generische Operation swap
in C ++ 03 führt eine temporäre Variable ein und führt drei Kopienkonstruktionen aus. In C ++ 11 gibt es move-semantics und die Objekte werden eher verschoben als kopiert. Geben Sie für Ihre eigenen Typen eine Datenstruktur an, die nur einen Zeiger auf die tatsächlichen Daten enthält. Sie sollten diese Prozedur optimieren, damit sie in konstanter Zeit abläuft:
In C ++ 03 können Sie std::swap
entweder spezialisieren oder Ihre eigene Funktion swap
in Ihrem Namespace implementieren (siehe die beiden oberen Antworten zu dieser Frage) , um das Swapping zu optimieren: Tauschen Sie einfach jedes Mitglied in Ihrer Klasse gegen ihre Daten aus. Für das Datenstrukturbeispiel, das nur einen Zeiger enthält, vertauschen Sie einfach die Zeiger.
In C ++ 11 gibt es die neue move-Semantik , mit der Sie die Bewegung der Daten von einem zu einem anderen Objekt implementieren können Ergebnis in einem sehr ähnlichen Verhalten. (Verschiebungssemantik wurde für allgemeinere Probleme wie das Tauschen von zwei Objekten eingeführt: Wenn ein Objekt nicht mehr benötigt wird, aber ein anderes "Kopie" des ersten sein muss, kann es einfach verschoben werden.) Lesen Sie über Verschiebungssemantik und Verschiebe Konstruktor für Details.
Für sowohl C ++ 03 als auch C ++ 11 gibt es einen alternativen Weg: Sie können implizit geteilte Daten implementieren und kopieren -write für schwere Klassen wie Datenstrukturen. Im obigen Beispiel, in dem Ihre Datenstruktur einen Zeiger auf die tatsächlichen Daten enthält, implementieren Sie die Referenzzählung. Wenn Sie die Datenstruktur kopieren, erhöhen Sie einfach den Referenzzähler um eins. Stellen Sie beim Ändern der Daten sicher, dass es nicht freigegeben ist (ref count = 1), andernfalls "trennen" Sie es, indem Sie es nur dann kopieren. Dies führt zu einer konstanten Kopier- und Tauschoperation.
Allgemeiner Fall: Mehrere beliebige Ausdrücke
Für andere Anweisungen, die nicht -abhängig sind, wie (a, b) = (x, y)
, schreibe sie einfach "wie sie sind", und sie wird mindestens perfekt pipelined laufen, da sie keine Abhängigkeit haben :
Wenn sie -abhängig sind, wie Ihr Beispiel in der Bearbeitung, können Sie sie aufteilen und Provisorien einführen. Du wirst dir keinen Gefallen tun, wenn du versuchst, das mit einigen ausgefallenen Ausdruckstricks wie xor-ing zu lösen. Der Compiler kennt eine Menge Tricks für Assembler (wie xchg
), Sie kennen nur Tricks, um solche in reinem C ++ (wie xor) auszudrücken.
In C ++ 11 gibt es std::tuple
und std::tie
, die Ihnen erlauben um mehrere Ausdrücke ohne Einführung von Provisorien zuzuweisen (sie werden im Hintergrund eingeführt, um die im Tupel gespeicherten Werte zu speichern und zu optimieren, entweder ganz weg oder zumindest nur mit Registern, um sie wenn möglich zu halten):
Beachten Sie, dass die Typen des Paares / Tupel auf der rechten Seite den Zielwerten auf der linken Seite entsprechen müssen, da die Konvertierung hier nicht implizit ist. Wenn Sie auf Probleme stoßen, führen Sie static_cast
auf der rechten Seite aus, sagen Sie std::make_tuple
die expliziten Typen oder verwenden Sie einfach den Konstruktor für std::tuple
, der explizite Typen benötigt, wie:
Wenn x
und y
reine Ganzzahlen sind, gibt es verschiedene schnelle Tricks, um sie in einer Zeile zu tauschen: