2014-02-11 6 views

Antwort

29

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.

+2

Danke, das erklärt alles. – BetterWang

+0

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. –

+0

@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

8

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

1

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); 
1

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.12erlaubt 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.

Verwandte Themen