2015-09-25 23 views
18

Podczas testowania kompilatora VS2015 C++ natknąłem się na dziwny błąd ze słowem kluczowym default. Jeśli mam zrobić:Możliwy błąd w obsłudze słowa kluczowego `default` w VS2015 C++

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

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

uzyskać

błędu C2280: 'Dummy :: Dummy (const Dummy &)': próbuje odwołać usuniętą funkcję
uwaga: patrz deklaracja „Manekina: : Dummy”

Ale jeśli mogę użyć pustego konstruktora

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

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

Kod się kompiluje. Uruchomienie pierwszego przykładu z g++ lub clang nie powoduje błędu.

Dlaczego użycie domyślnego konstruktora z VS2015 powinno próbować użyć konstruktora kopiowania, który nie jest w g ++ lub clang?

+0

Co otrzymasz od 'const Dummy & r2 {Dummy()};'? –

+0

Powiązane: [Kopiuj/przenieś elizę w stosunku do jawnie skasowanych konstruktorów kopiowania/przenoszenia] (http: // stackoverflow.com/questions/20589622) –

+0

Zobacz http://stackoverflow.com/questions/31264984/c-compiler-error-c2280-attempting-to-reference-a-deleted-function-in-visual –

Odpowiedz

9

Jest to z pewnością błąd w VS 2015.

w C++ 11, przypisując tymczasowy do const odniesienia nie musi wywołać konstruktor kopiujący, ale VS 2015 nie.

Można to sprawdzić z

#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; 
} 

sporządzoną na VS 2013, 2015, GCC i brzękiem. Tylko VS (dowolna wersja) wywołuje konstruktor kopiowania, jeśli konstruktor klasy zdefiniowano jako = default.

myślę VS compiiler jeszcze w 2015 roku błędnie używa starych C++ 03 standardowych zasad dla tego (8.5.3.5 C++ 03):

Jeśli wyrażenie inicjująca jest rvalue z T2 A Klasa typu i „CV1 T1” jest kompatybilna z odniesienia „CV2 T2” odwołanie jest związana w jeden z następujących sposobów (wybór jest realizacja zdefiniowane):

- Wniosek jest zobowiązany do obiekt reprezentowany przez wartość r (patrz 3.10) lub do pod-obiektu wewnątrz tego obiektu.

- Utworzono tymczasowy typ "cv1 T2" [sic] i wywoływany jest konstruktor, aby skopiować cały obiekt rvalue do pliku tymczasowego. Odwołanie o numerze jest powiązane z tymczasowym lub z obiektem podrzędnym w trybie tymczasowym .

Konstruktor, który zostanie użyty do wykonania kopii, będzie można wywołać , niezależnie od tego, czy kopia jest rzeczywiście wykonywana.

Programiści VS wybrali drugą drogę. Poprawiono to dla pustego konstruktora zdefiniowanego przez użytkownika ({}), ale zapomniałem zrobić to dla domyślnych konstruktorów (= default).

PS. Bug on MS Connect (proszę głosuj)

+0

Odpowiedź S.T.L.: https://twitter.com/StephanTLavavej/status/648949525684465664 – vladon

Powiązane problemy