Warum kompiliert es überhaupt?Warum kann ich Struktur mit einem Zeiger zuweisen?
Ich versuchte mit GCC (GCC) 4.6.2. Wie kann ich eine Struktur mit einem Zeiger zuweisen?
Warum kompiliert es überhaupt?Warum kann ich Struktur mit einem Zeiger zuweisen?
Ich versuchte mit GCC (GCC) 4.6.2. Wie kann ich eine Struktur mit einem Zeiger zuweisen?
Sie treffen die Tatsache, dass Sie Ihren Konstruktor nicht als explicit
markiert haben und somit für implizite Konvertierungen verwendet werden können.
new UE(true)
gibt einen Zeiger zurück. Alle Zeiger können implizit in bool
konvertiert werden, was zu true
führt, wenn sie nicht null sind. UE
kann implizit aus einem bool
aufgebaut werden. Der von new
zurückgegebene Zeiger wird also in bool
konvertiert, der unter Verwendung Ihres Konstruktors in UE
konvertiert wird, und dann wird der Kopierzuweisungsoperator von UE
aufgerufen. Natürlich ist der von new
zugeteilte Speicher durchgesickert.
Die Take-Home-Nachricht lautet: Markieren Sie Ihre Konstruktoren mit einem Argument immer als explicit
, es sei denn, Sie möchten, dass sie für implizite Konvertierungen verwendbar sind. Mit "Konstruktor mit einem Argument" meine ich einen, der mit einem einzigen Argument aufgerufen werden kann. Entweder weil es einen Parameter hat, oder es hat mehr und alle Parameter nach dem ersten haben Standardargumente.
Danke, das erklärt alles. – BetterWang
Ich wünschte wirklich gcc würde eine Warnung dafür erzeugen. Es scheint, als sollte es von "Dingen, die Sie tun möchten" unterschieden werden. Cppcheck (1.63.1) hat es nicht verstanden. g ++ 4.7.2 hat es nicht verstanden. –
@ColinDBennett Du meinst wegen der 'neuen'? Moderner C++ - Code sollte sowieso nicht viele 'neue' Aufrufe enthalten, also würde es ziemlich selten zutreffen. Und mit jeder anderen Möglichkeit, einen Zeiger zu erhalten, ist eine solche Konvertierung ein faires Spiel und ich wäre ziemlich verärgert, wenn ich es beabsichtigt hätte und eine Warnung bekommen hätte. – Angew
Es gibt eine implizite Konvertierung von jedem Zeiger auf bool
. Daher ruft dieser Code implizit den Konstruktor des einzelnen Arguments auf, nachdem der Zeiger in einen bool
Wert
umgewandelt wurde. Eine Möglichkeit, dies zu beheben, besteht darin, den Konstruktor für einzelne Parameter explizit zu machen.
struct UE{
explicit UE(bool a = true) { };
};
Dies wird den Code kompilieren, wenn der Konstruktor verhindern ausdrücklich
Jeder Skalar Typ boolean Wert kann in Abhängigkeit davon, wahr oder falsch umgewandelt aufgerufen wird, ob dessen Wert auf Null oder nicht gleich ..
In dieser Erklärung
ue = new UE(true);
die implizit durch den Compiler Kopie Zuweisungsoperator definiert wird aufgerufen. Da Ausdruck new UE (true) ungleich Null ist, kann es implizit in den booleschen Wert true konvertiert werden. Die Klasse UE hat den Umwandlungskonstruktor
UE(bool a = true);
, der ein Objekt vom Typ bool in ein Objekt vom Typ UE konvertiert.
Um eine solche Nutzung zu verhindern Sie den Konstruktor definieren sollte als explizite
explicit UE(bool a = true);
Wenn Sie Sie diese Arbeit nicht explizit Konstruktor markieren:
explicit UE(bool a = true) { };
dies ist, weil es eine implizite Konvertierung ist aus der Zeiger auf ein Bool, können wir sehen, dass dies von Entwurf C++ Standardabschnitt 4.12
erlaubt ist Boolean Konvertierungen sagt (Emphasis:):
A prvalue der Arithmetik, unscoped Enumeration, Zeiger oder Zeiger auf Elementtyp kann zu einer prvalue vom Typ bool umgewandelt werden.
Es kompiliert in VS2010. – herohuyongtao
@herohuyontao Die Frage ist warum. Die Antwort sind implizite Konvertierungen. – juanchopanza
@HenkHolterman 'new' gibt einen Zeiger zurück. –