2015-09-25 10 views
18

Durante il test del compilatore C++ VS2015 mi sono imbattuto in uno strano bug con la parola chiave default. Se faccio:Possibile errore nella gestione della parola chiave `default` in VS2015 C++

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

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

ottengo

errore C2280: 'Dummy :: Dummy (const Dummy &)': il tentativo di fare riferimento a una funzione eliminata
nota: vedi dichiarazione di 'Dummy: : Dummy'

Ma se io uso un costruttore vuoto

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

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

Il codice viene compilato. L'esecuzione del primo esempio con g++ o clang non produce alcun errore.

Perché utilizzare il costruttore predefinito con VS2015 tenta di utilizzare il costruttore di copie in cui non è in g ++ o clang?

+0

Cosa ottieni da 'const Dummy & r2 {Dummy()};'? –

+0

Correlati: [Copia/sposta elisione contro i costruttori copia/sposta eliminati in modo esplicito] (http: // stackoverflow.it/questions/20589622) –

+0

Si prega di consultare questo http://stackoverflow.com/questions/31264984/c-compiler-error-c2280-attempting-to-reference-a-deleted-function-in-visual –

risposta

9

E 'sicuramente un bug in VS 2015.

In C++ 11, l'assegnazione temporanea di riferimento const non deve chiamare il costruttore copia, ma VS 2015 fa.

È possibile controllare con

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

compilato su VS 2013, 2015, gcc e clang. Solo VS (qualsiasi versione) chiama copy constructor, se costruttore di classi definito come = default.

Credo VS compiiler ancora nel 2015 utilizza erroneamente vecchi C++ 03 regole standard per questo (8.5.3.5 di C++ 03):

Se l'espressione di inizializzazione è un rvalue, con un T2 classe tipo e "CV1 T1" è riferimento compatibile con "cv2 T2", il riferimento è legato in uno dei seguenti modi (la scelta dipende dall'implementazione):

- il riferimento è destinata a l'oggetto rappresentato dal valore di rvalue (vedi 3.10) o da un oggetto secondario all'interno dell'oggetto.

- Un temporaneo di tipo "cv1 T2" [sic] viene creato e un costruttore viene chiamato per copiare l'intero oggetto rvalue nel temporaneo. Il riferimento è associato al temporaneo o ad un sottooggetto all'interno del temporaneo .

Il costruttore che sarebbe stato utilizzato per eseguire la copia deve essere chiamabile indipendentemente dal fatto che la copia sia effettivamente eseguita.

Gli sviluppatori di VS hanno scelto la seconda strada. L'hanno corretto per costruttore vuoto definito dall'utente ({}), ma si è dimenticato di farlo per i costruttori predefiniti (= default).

PS. Bug on MS Connect (votare)

+0

Risposta di S.T.L.: https://twitter.com/StephanTLavavej/status/648949525684465664 – vladon

Problemi correlati