2015-06-26 6 views
6

Supponiamo di avere una classe chiamata del prodotto, definita in questo modo:Quando è consentito al compilatore di ottimizzare l'inizializzazione di stile auto + brace?

class Product 
    { 
    public: 
     Product(const char *name, int i); 
     Product(Product &&rhs); 
     Product(const Product &rhs); 
     ~Product(); 
    private: 
     const char *m_name; 
     int m_i; 
    }; 

e si inizializza una variabile in questo modo:

auto p = Product{"abc",123}; 

ho pensato che la norma dettata che un compilatore deve logicamente effettuare le seguenti operazioni :

  • costruire un prodotto temporanea
  • mossa-costrutto p (usando il prodotto temporaneo)

Ma che al compilatore è stato permesso di ottimizzare questo modo che p sia costruito direttamente.

Ho verificato questo (Visual Studio 2013) e infatti, il compilatore lo ottimizza, anche se abbiamo il nostro costruttore di spostamento personalizzato (non predefinito). Questo va bene.

Tuttavia, se si elimina esplicitamente il copy-e Move-costruttore, in questo modo:

class Product 
    { 
    public: 
     Product(const char *name, int i); 
     Product(Product &&rhs) = delete; 
     Product(const Product &rhs) = delete; 
     ~Product(); 
    private: 
     const char *m_name; 
     int m_i; 
    }; 

L'inizializzazione auto + brace compila ancora. Ho pensato che il compilatore dovesse impedirlo perché non è consentito copiare o spostare.

abbastanza strano, se faccio il copy-eliminato e Move-costruttore privato, in questo modo:

class Product 
    { 
    public: 
     Product(const char *name, int i); 
     ~Product(); 
    private: 
     Product(Product &&rhs) = delete; 
     Product(const Product &rhs) = delete; 
     const char *m_name; 
     int m_i; 
    }; 

Poi l'inizializzazione auto + brace non compilatore più.

error C2248: 'Product::Product' : cannot access private member declared in class 'Product' 

È questo comportamento previsto? Si tratta di un bug in Visual Studio 2013 (aggiornamento 3)?

Nota: Ho provato la compilazione di questo su ideone e ci si rifiuta infatti di compilare l'inizializzazione quando il copy-e Move-costruttori vengono eliminati (e pubblico). Quindi penso che questo sia un bug di Visual Studio.

+1

Cordiali saluti in Visual Studio 2013 * * compilatore ha generato costruttori muovere e spostare gli operatori di assegnazione sono ** ** non supportate (se si può definire il proprio). [Ecco un elenco di conformità C++ 11 (non) di VS2013] (https://msdn.microsoft.com/en-us/library/hh567368.aspx#featurelist) – CoryKramer

+0

Versione compilatore 18.00.30723. Potrebbe essere introdotto questo bug tra il 21005 e il 30723? – Patrick

+0

@Patrick NVM. Una volta ho fornito parentesi vuote per il costruttore e il distruttore che ha compilato su VS. – NathanOliver

risposta

1

lo standard è molto chiaro come accennato prima, indicando che si tratta di un bug nel compilatore cl. Non si può mai essere sicuri, anche se se un compilatore sta dicendo qualcosa e tutti gli altri non sono d'accordo, mi aspetto che questa sia una delle molte implementazioni non conformi allo standard del compilatore MSVC.

L'interpretazione di clang versione 3.7 (svn-build):

t.cpp:19:7:{19:11-19:30}: error: call to deleted constructor of 'Product' 
     [Semantic Issue] 
     auto p = Product{"abc", 123}; 
      ^ ~~~~~~~~~~~~~~~~~~~ 
t.cpp:8:2: note: 'Product' has been explicitly marked deleted here 
     [Semantic Issue] 
     Product(Product &&rhs) = delete; 
     ^
1 error generated. 
make: *** [t.o] Error 1 

L'interpretazione di gcc 4.8:

t.cpp: In function ‘int main()’: 
t.cpp:19:29: error: use of deleted function ‘Product::Product(Product&&)’ 
    auto p = Product{"abc", 123}; 
          ^
t.cpp:8:2: error: declared here 
    Product(Product &&rhs) = delete; 
^
make: *** [build/gcc/t.o] Error 1 

anche tenere a mente che la Explicitly Defaulted and Deleted Functions sono novità dal MSVC 2013 e l'attuazione di esso non è ancora completa. Come se non capisse ancora = valore predefinito per i costruttori di mosse.

La mia ipotesi sarebbe che MSVC 2013 non controlli il costruttore di spostamenti o semplicemente ricada al costruttore di copie.

Potrebbe essere interessante controllare MSVC 2015, poiché sembra avere una (più) completa implementazione di queste costruzioni.

JVApen

+1

Visual Studio 2015 sta effettivamente dando un errore su questo (prodotto :: prodotto (prodotto &&) ': tentativo di fare riferimento a una funzione eliminata). Quindi era chiaramente un bug in Visual Studio 2013. – Patrick

0

In linea

auto p = Product{"abc",123}; 

il segno di uguale non è il che denota l'operatore di assegnazione, ma è solo la sintassi per un inizializzatore. Quindi, il compilatore non sta ottimizzando nulla, ma sta solo facendo l'inizializzazione.

+0

Allora perché fallisce quando il costruttore di mosse e copie viene cancellato E privato? – Patrick

+0

Questo non è corretto. Secondo lo standard, il compilatore deve prima costruire un temporaneo, quindi spostarlo - costruirlo nella variabile. Ma al compilatore è permesso di ottimizzare questo (costruendo direttamente la variabile), a condizione che l'effetto logico sia lo stesso di costruzione + moveconstruction, che non è il caso se il costruttore di movimento viene cancellato. – Patrick

Problemi correlati