copy-initialization

___ answer6163192 ___

In jedem Compiler wird der syntaktische [und semantische] Analyseprozess vor dem Codeoptimierungsprozess durchgeführt.

Der Code muss syntaktisch gültig sein, sonst wird er nicht kompiliert. Es ist nur in der späteren Phase (d. H. Code-Optimierung), dass der Compiler beschließt, die temporäre, die es erstellt, zu elide.

Sie brauchen also einen zugänglichen copy-tor.

    
___ answer6163448 ___

C ++ erlaubt explizit mehrere Optimierungen mit dem Copy-Konstruktor, die die Semantik des Programms tatsächlich verändern. (Dies steht im Gegensatz zu den meisten Optimierungen, die die Semantik des Programms nicht beeinflussen). Insbesondere gibt es mehrere Fälle, in denen der Compiler ein vorhandenes Objekt erneut verwenden darf, anstatt es zu kopieren, wenn es weiß, dass das vorhandene Objekt nicht mehr erreichbar ist. Dies (Kopieraufbau) ist ein solcher Fall; Ein anderer ähnlicher Fall ist die "Rückgabewert-Optimierung" (RVO), wobei C ++, wenn Sie die Variable deklarieren, die den Rückgabewert einer Funktion enthält, diese auf dem Frame des Aufrufers zuweisen kann, so dass sie nicht benötigt wird um es zurück zum Aufrufer zu kopieren, wenn die Funktion beendet ist.

Im Allgemeinen spielen Sie in C ++ mit Feuer, wenn Sie einen Kopierkonstruktor definieren, der Nebenwirkungen hat oder irgendetwas anderes als nur das Kopieren tut.

    
___ answer6163086 ___

RVO und NRVO, Kumpel. Tadellos guter Fall der Kopie ellision.

    
___ qstnhdr ___ Seltsames Verhalten der Kopierinitialisierung, ruft den Copy-Konstruktor nicht auf! ___ tag123c ___ C ++ ist eine universelle Programmiersprache. Es wurde ursprünglich als Erweiterung von C entworfen und behält eine ähnliche Syntax, ist aber jetzt eine komplett andere Sprache. Verwenden Sie dieses Tag für Fragen zu Code, der mit einem C ++ - Compiler kompiliert werden soll. ___ answer6163385 ___

Fragen Sie, warum der Compiler die Zugriffskontrolle durchführt? 12.8 / 14 in C ++ 03:

  

Ein Programm ist schlecht formatiert, wenn die Kopie   Konstruktor oder die Kopierzuordnung   Operator für ein Objekt ist implizit   verwendet und die spezielle Mitgliedfunktion   ist nicht zugänglich

Wenn die Implementierung "den Kopieraufbau weglässt" (erlaubt bis 12.8 / 15), glaube ich nicht, dass der copy ctor nicht mehr "implizit verwendet" wird, sondern einfach nicht ausgeführt wird.

Oder fragen Sie, warum der Standard das sagt? Wenn die Eliminierung der Kopie eine Ausnahme von dieser Regel für die Zugriffsprüfung wäre, wäre Ihr Programm in Implementierungen, die die Elision erfolgreich durchführen, wohlgeformt, aber in Implementierungen, die dies nicht tun, schlecht gebildet.

Ich bin mir ziemlich sicher, dass die Autoren das für eine schlechte Sache halten würden. Natürlich ist es einfacher, portablen Code auf diese Weise zu schreiben - der Compiler sagt Ihnen, wenn Sie Code schreiben, versucht ein nicht kopierbares Objekt zu kopieren, selbst wenn die Kopie in Ihrer Implementierung nicht vorhanden ist. Ich vermute, dass es auch Implementierern unangenehm sein könnte, herauszufinden, ob die Optimierung erfolgreich sein wird bevor der Zugriff überprüft wird (oder die Zugriffsprüfung verzögert wird, nachdem die Optimierung versucht wurde), obwohl ich keine Ahnung habe, ob dies gerechtfertigt ist Rücksicht.

  

Könnte dieses Verhalten gefährlich sein? ich   Ich meine, ich könnte etwas anderes Nützliches tun   Ding in der Kopie-Ctor, aber wenn es   nennt es nicht, dann nicht   das Verhalten des Programms ändern?

Natürlich könnte es gefährlich sein - Seiteneffekte in Kopierkonstruktoren treten genau dann auf, wenn das Objekt tatsächlich kopiert wird, und Sie sollten es entsprechend gestalten: Der Standard sagt, dass Kopien entfernt werden können, also setzen Sie keinen Code in a Kopieren Sie den Konstruktor, es sei denn, Sie freuen sich, dass er unter den in 12.8 / 15 definierten Bedingungen veröffentlicht wird:

%Vor%     
___ tag123initialisierung ___ Die Initialisierung beschäftigt sich mit der Aufgabe, den Inhalt Ihrer Datenstruktur zu initialisieren. Es ist eine gängige Praxis in statisch typisierten Sprachen. ___ answer6163320 ___

Hier Sie können dies finden (mit Ihrem Kommentar;)):

  

[der Standard] sagt auch, dass die temporäre Kopie   kann elided sein, aber die Semantik   Einschränkungen (zB Zugänglichkeit) der   Kopierkonstruktor muss immer noch sein   überprüft.

    
___ answer6163127 ___

Dies ist eine Optimierung durch den Compiler.

Bei der Auswertung: %code% anstelle von:

  1. erstellt zuerst ein temporäres Objekt über %code% ;

  2. Konstruieren von %code% durch den Kopierkonstruktor und Übergeben des temporären;

Der Compiler erstellt einfach %code% mit %code% .

    
___ tag123copyinitialisierung ___ hilf uns dieses Wiki zu bearbeiten ___ tag123copyconstructor ___ Ein Kopierkonstruktor ist ein Konstruktor, der ein neues Objekt erstellt, das ein Klon eines vorhandenen Objekts ist. Der Begriff wird meist in der Programmiersprache C ++ verwendet, wobei Kopierkonstruktoren einen besonderen Status haben. ___ qstntxt ___

Ich habe den Unterschied zwischen Direktinitialisierung und Kopierinitialisierung (§8.5 / 12) gelesen:

%Vor%

Was ich verstehe, wenn ich über Kopier-Initialisierung ist, dass benötigt wird zugänglich & amp; nicht expliziter Kopierkonstruktor , sonst würde das Programm nicht kompilieren. Ich habe es verifiziert, indem ich den folgenden Code geschrieben habe:

%Vor%

GCC gibt einen Fehler ( ideone ) aus und sagt:

  

prog.cpp: 8: Fehler: 'A :: A (const A & amp;)' ist privat

Bis jetzt ist alles in Ordnung, bekräftigt, was Herb Sutter sagt ,

  

Die Initialisierung der Kopie bedeutet, dass das Objekt mit dem Kopierkonstruktor nach dem ersten Aufruf einer benutzerdefinierten Konvertierung initialisiert wird und der Form "T t = u;" entspricht:

Danach habe ich den copy-ctor zugänglich gemacht, indem ich das %code% Schlüsselwort kommentiert habe. Jetzt würde ich natürlich Folgendes erwarten:

  

A (const A & amp;)

Aber zu meiner Überraschung druckt das stattdessen ( ideone ):

  

A (int i)

Warum?

Gut, ich verstehe, dass zuerst ein temporäres Objekt vom Typ %code% aus %code% erstellt wird, das %code% type ist, indem %code% verwendet wird, indem die Konvertierungsregel hier angewendet wird (§8.5 / 14 ), und dann sollte copy-ctor aufgerufen werden, um %code% zu initialisieren. Aber es tat es nicht. Warum?

Wenn eine Implementierung es erlaubt, Copy-Konstruktor (§8.5 / 14) aufzurufen, warum akzeptiert sie dann nicht den Code, wenn der Copy-Konstruktor %code% deklariert wird? Schließlich nennt es es nicht. Es ist wie ein verwöhntes Kind, das zuerst irritierend um ein spezifisches Spielzeug bittet, und wenn du ihm eines gibst, das spezifische , wirft er es hinter deinem Rücken weg. : |

Könnte dieses Verhalten gefährlich sein? Ich meine, ich könnte ein anderes nützliches Ding im copy-ctor machen, aber wenn es es nicht aufruft, ändert es dann nicht das Verhalten des Programms?

    
___
1
Antwort

Referenzbindung durch mehrdeutigen Konvertierungsoperator

%Vor% Sowohl clang als auch gcc geben einen mehrdeutigen Konvertierungsoperator, aber Visual Studio kompiliert ok und gibt "operator const CL2 & amp;" aus. Wie muss die Norm stimmen? Wie ich erkannt habe, wird die Umwandlung von CL1 in const CL...
06.12.2015, 16:35
1
Antwort

Warum ist die Kopierinitialisierung so wie sie ist? Warum benötigen Sie den Kopierkonstruktor? [Duplikat]

Und bei der Kopierinitialisierung meine ich so: %Vor% Trotz der jahrelangen Programmierung in C ++ habe ich nie realisiert, dass der obige Code den Kopierkonstruktor benötigt (Danke an jogojapan). Das Temporäre war immer elide gewesen, u...
04.12.2012, 04:18
6
Antworten

Seltsames Verhalten der Kopierinitialisierung, ruft den Copy-Konstruktor nicht auf!

Ich habe den Unterschied zwischen Direktinitialisierung und Kopierinitialisierung (§8.5 / 12) gelesen: %Vor% Was ich verstehe, wenn ich über Kopier-Initialisierung ist, dass benötigt wird zugänglich & amp; nicht expliziter Kopierkonstrukt...
28.05.2011, 16:56