2016-06-11 9 views
3

Werden Provisorien in C++ generiert, wenn eine Literalkonstante/Basistypen einer Variablen zugewiesen sind? Unterscheidet sich dies zwischen C++ - Spezifikationen (C++ 98, C++ 11, C++ 14, C++ 17 usw.)?Gibt es einen C++ temporären rvalue für Konstanten

int a = 1; // 1 here is likely loaded in microcode level, right? But not guaranteed not to generate a temp value 

int b = 1+2; // evaluated to 3 at compile time as const, also 3 might not exist in microcode. Likely temp value 

auto c = 3; // creates an int based on 3. No temp value 

int a{1}; //no temp value? 

Ich lese https://herbsutter.com/2013/05/13/gotw-2-solution-temporary-objects/.

Auch ich nehme an, ich auf alle diese völlig falsch bin

+3

Fragen Sie nach der Abstraktion, die der Sprachstandard beschreibt, oder nach dem Maschinencode, der von einem Compiler in der Praxis ausgegeben wird? –

+2

Wer sagt, dass diese Variable sogar im endgültigen Code existiert? Sie fragen nach Details, die nur Ihr Disassembler kennt. AFAIK, C++ ermöglicht es Compilern, so viele Provisorien wie ihre Maschinenherzen zu erstellen. Die erste Zeile könnte 'int a = int (int (int (int (1)))) sein, für alles was sie interessiert. – GManNickG

+0

@OliverCharlesworth Ich denke, eine Mischung aus beiden – MathFromScratch

Antwort

2

Wenn wir genauer sein werden wir temporäre Objekte und temporäre Werte unterscheiden. Ein temporäres Objekt gehört zu Klassentypen. Dies ist es, was der C++ Standard diskutiert und was Leute normalerweise meinen, wenn sie von "Provisorien" sprechen. Wenn Menschen über temporäre Werte sprechen, dann meinen sie Zwischenergebnisse. d.h. Austauschen von Werten aus Registern.

Alle Ihre Beispiele:

int a = 1; 
int b = 1+2; 
auto c = 3; 
int d{1}; 

erzeuge keine „Provisorien“, weil keine erstellt werden müssen. "1 + 2" wird wahrscheinlich zu einer Konstante gefaltet. Es müssen keine Opcodes generiert werden. Die minimale Montage für dieses Programm ist:

a: 
     .long 1 
b: 
     .long 3 
c: 
     .long 3 
d: 
     .long 1 

Die GOTW Sie mehr mit der übergeordneten Debatte über „vorbei Wert“ und minimiert unnötige Kopien der Klasse temporäre Objekte verknüpft ist. Es gibt kaum einen Grund, sich um literale Typen zu kümmern, ob Provisorien erstellt werden oder nicht, es sei denn, Sie optimieren vorzeitig.

+1

Können Sie den Begriff * temporärer Wert * aus dem Standard zitieren? Wenn nicht, können Sie sicher sein, dass Sie von einer typischen C++ - Implementierung sprechen, nicht von C++? – Yakk

+1

@Yakk Ich habe versucht, "temporäres Objekt" (im Standard) und "temporärer Wert" (nicht im Standard, sondern in der Sprache verwendet) zu unterscheiden. "Temperaturwert" ist das, was OP in seiner Frage verwendet. –

3

C++ Die Sprache ist durch den Standard definiert. Im Standard beschreibt es das Verhalten einer abstrakten Maschine, die mit wohlgeformten Programmen arbeitet, die das vom Standard definierte Verhalten ausführen.

Eine Kernregel von C++ ist die as-if Regel. Unter der as-if Regel ist der generierte Code des Compilers frei, sich zu verhalten jedoch wünscht er, solange sein Verhalten, das unter dem Standard beobachtbar ist, übereinstimmt, was der Standard angibt.

Es gibt keine Möglichkeit, unter dem Standard die Existenz des 1 in 1+2 zu beobachten. Unter dem Standard kann der Compiler also Code kompilieren, für den 1 niemals existiert hat, und einfach die Nummer 3 generieren.

Was mehr ist, wenn Sie die nie x Variable verwenden, die Anweisung

int x = 1+2+3+4; 

keine Wirkung hat. Also ist es den Compilern frei, sie niemals zu benutzen. In der Tat, Sie nehmen nie einen Verweis auf den Wert x oder ändern Sie ihren Wert, dann kann die Variable x vollständig aus dem Programm entfernt werden. Wann immer es verwendet wird, kann der Wert 10 es ersetzen.

Typischerweise optimierende Compiler etwas tun „statische einfache Zuordnung“ genannt, wo auch wenn Sie x mehrfach zuweisen es behandelt sie tatsächlich als eine Folge von Zuweisungen verschiedenen Variablen.Nur wenn Sie eine Referenz oder einen Zeiger auf x nehmen, bricht dies zusammen.

So

int x = 1+2+3+4; 
std::cout << x; 
x += 20; 
std::cout << x; 

als

const int x_0 = 10; 
std::cout << x_0; 
const int x_1 = x_0 + 20; 
std::cout << x_1; 

und dann den offensichtlichen Optimierungen einfach Drucken 10 und 30 fällt direkt aus behandelt werden.

Wenn Sie über C++ auf diese Weise denken, müssen Sie darauf achten, was beobachtbares Verhalten ist, und wissen, dass der Compiler frei ist, den Rest zu verwerfen. Mit ein wenig Vorsicht können Sie also Zero-Cost-Abstraktionen erstellen, bei denen Zwischenergebnisse zur Laufzeit nie wirklich existieren.

+0

Zur Klarstellung, das "wie-wenn" gilt sowohl für den Standard (eine Compilerinterpretation der C++ - Definition zu einer anderen), als auch was der Benutzer erwartet (das resultierende Programm während der Ausführung)? Im letzteren Fall konnte das nicht etwas kaputt machen, wenn das Betriebssystem einen Wert an dieser Adresse erwartete, aber der Compiler entschied, dass das Programm selbst niemals eine Konstante verwendete? – MathFromScratch

+1

@MathFromScratch Die "als-ob" -Regel ist nur der Standard. Die Erwartungen der Benutzer sind nicht das (direkte) Problem des Standards. Wenn das Betriebssystem einen Wert an einer Adresse erwartet, muss entweder der C++ - Compiler zusätzliche Garantien hinzufügen oder es muss eine API vorhanden sein, mit der die Adresse an das Betriebssystem übergeben wird. – Yakk

Verwandte Themen