In dem obigen Code, wie ich es verstehe, obwohl der Code-Konstruktor in den meisten Fällen weggelassen wird, ist es immer noch semantisch erforderlich, dass er aufgerufen wird. Meine Frage ist, ist der Aufruf explizit oder implizit? Für eine lange Zeit habe ich die Schlussfolgerung, dass der Aufruf von AAA::AAA(int)
implizit ist, aber der Aufruf an den Kopierkonstruktor nicht. Heute habe ich versehentlich g ++ bekommen, um den obigen Code zu kompilieren und es wurde ein Fehler gemeldet. (VC12 kompiliert OK.)
In Abschnitt 8.5 des Standards:
Wenn der Zieltyp ein (möglicherweise cv-qualifizierter) Klassentyp ist:
Wenn die Initialisierung eine direkte Initialisierung ist oder wenn es sich um eine Kopierinitialisierung handelt, bei der die cv-unqualifizierte Version der Quelle ist type ist dieselbe Klasse wie oder eine abgeleitete Klasse der Klasse Ziel, Konstrukteure werden berücksichtigt. Die anwendbaren Konstruktoren werden aufgezählt (13.3.1.3), und der beste wird durch Überladung gewählt Auflösung (13.3). Der so ausgewählte Konstruktor wird zum Initialisieren aufgerufen das Objekt mit dem Initialisierungsausdruck oder der Ausdrucksliste als sein Argumente). Wenn kein Konstruktor angewendet wird oder die Überladungsauflösung ist mehrdeutig, die Initialisierung ist schlecht ausgebildet.
Andernfalls (d. h. für die verbleibenden Fälle von Kopierinitialisierung) benutzerdefinierte Konvertierungssequenzen, die von der Quelle konvertieren können Geben Sie den Zieltyp ein oder (wenn eine Konvertierungsfunktion verwendet wird) zu einer davon abgeleiteten Klasse werden wie in 13.3.1.4 beschrieben gezählt, und das beste wird durch Überladungsauflösung gewählt (13.3). Wenn die Konvertierung kann nicht durchgeführt werden oder ist mehrdeutig, die Initialisierung ist schlecht geformt. Die ausgewählte Funktion wird mit dem Initialisierer aufgerufen Ausdruck als Argument; Wenn die Funktion ein Konstruktor ist, der Aufruf initialisiert ein temporäres der cv-unqualifizierten Version des Zieltyp Das Temporäre ist ein Prvalue. Das Ergebnis des Anrufs (das ist die temporäre für den Konstruktor Fall) wird dann verwendet direct-initialize , nach den obigen Regeln, das Objekt, das ist das Ziel der Kopierinitialisierung. In bestimmten Fällen Die Implementierung erlaubt es, das damit verbundene Kopieren zu eliminieren direkte Initialisierung durch direktes Konstruieren des Zwischenergebnisses in das Objekt, das initialisiert wird; siehe 12.2, 12.8.
Das fett dargestellte direct-initialize
in den obigen Anführungszeichen bedeutet, dass der Aufruf zum Kopieren des Konstruktors explizit ist, oder? Ist g ++ falsch oder meine Interpretation des Standards falsch?
Sieht wie dieser Fehler aus: g ++ kann im zweiten Schritt der Kopierinitialisierung keine expliziten Konstruktoren aufrufen
g ++ kann den folgenden Code nicht kompilieren
%Vor%Der zweite Schritt einer Kopierinitialisierung (siehe 8.5 / 16/6/2) ist a Direkt-Initialisierung, wobei explizite Konstruktoren berücksichtigt werden sollen als Kandidatenfunktionen.
Sieht so aus, als würde der Kopierkonstruktor nie aufgerufen. Nur Konstruktor wird aufgerufen. Der folgende Code kann den Kopierkonstruktor
aufrufen %Vor%Nicht sicher, warum G ++ es kompiliert.
Tags und Links c++ language-lawyer g++