2015-09-25 1 views
18

Beim Testen des C++ - Compilers VS2015 bin ich auf einen seltsamen Fehler mit dem Schlüsselwort default gestoßen. Wenn ich das tue:Möglicher Fehler bei der Behandlung des Schlüsselwortes `default` in VS2015 C++

struct Dummy 
{ 
    Dummy() = default; 
    Dummy(const Dummy &) = delete; 
}; 

int main() 
{ 
    const Dummy& ref = Dummy(); 
    return 0; 
} 

ich

Fehler C2280: 'Dummy :: Dummy (konst Dummy &)': Der Versuch, eine gelöschte Funktion
Notiz zu verweisen: Siehe Deklaration von ‚Dummy: : Dummy‘

Aber wenn ich einen leeren Konstruktor

struct Dummy 
{ 
    Dummy() {} 
    Dummy(const Dummy &) = delete; 
}; 

int main() 
{ 
    const Dummy& ref = Dummy(); 
    return 0; 
} 

Der Code wird kompiliert. Das Ausführen des ersten Beispiels mit g++ oder clang führt zu keinem Fehler.

Warum sollte die Verwendung des Standardkonstruktors mit VS2015 versuchen, den Kopierkonstruktor zu verwenden, wo es nicht in g ++ oder clang?

+0

Was bekommen Sie von 'const Dummy & r2 {Dummy()};'? –

+0

Zugehörig: [Elision versus explizit gelöschte Copy/Move-Konstruktoren kopieren/verschieben] (http: // stackoverflow.com/questions/20589622) –

+0

Bitte beachten Sie diese http://stackoverflow.com/questions/31264984/c-compiler-error-c2280-attempting-to-reference-a-deleted-function-invisual –

Antwort

9

Es ist definitiv ein Fehler in VS 2015

In C++ 11, konstante Referenz temporäre Zuordnung muss Copykonstruktor nicht nennen, aber VS 2015 der Fall ist.

Sie können es mit

#include <iostream> 

struct Dummy 
{ 
    Dummy() = default; 
    Dummy(const Dummy &) { std::cout << "copy ctor" << std::endl; } 
    void test() const { std::cout << "test" << std::endl; } 
}; 

int main() 
{ 
    const Dummy& ref = Dummy(); 
    ref.test(); 
    return 0; 
} 

auf VS kompiliert 2013 2015 gcc und Klirren. Nur VS (jede Version) ruft den Kopierkonstruktor auf, wenn der Klassenkonstruktor als = default definiert ist.

denke ich VS compiiler noch im Jahr 2015 fälschlicherweise alte C++ 03 Standardregeln für diesen (8.5.3.5 von C++ 03) verwendet:

Wenn der initializer Ausdruck ein R-Wert ist, mit T2 einem Klassentyp und „CV1 T1“ reference-kompatibel mit „CV2 T2“, das Referenz in einer der folgenden Weisen gebunden ist (die Wahl ist die Implementierung definiert):

- die Referenz ist, gebunden an das durch den rvalue (siehe 3.10) dargestellte Objekt oder ein Unterobjekt innerhalb dieses Objekts.

- Ein temporärer Typ "cv1 T2" [sic] wird erstellt, und ein Konstruktor wird aufgerufen, um das gesamte rvalue-Objekt in das temporäre Objekt zu kopieren. Die Referenz ist an das temporäre oder an ein Unterobjekt innerhalb der temporären gebunden.

Der Konstruktor, der zum Erstellen der Kopie verwendet wird, muss aufrufbar sein ob die Kopie tatsächlich erfolgt.

VS-Entwickler entschieden sich für den zweiten Weg. Sie haben dies für den leeren benutzerdefinierten Konstruktor ({}) korrigiert, aber vergessen, dies für defaulted (= default) Konstruktoren zu tun.

PS. Bug on MS Connect (bitte abstimmen)

+0

S.T.L.'s Antwort: https://twitter.com/StephantLavavej/status/648949525684465664 – vladon

Verwandte Themen