Qual è la differenza tra il vecchio alloctaor :: construct e il nuovo ed esplicito costruttore?


15

Come so, std::allocator<T>::constructaccetta solo due parametri nella versione precedente di C ++; il primo è un puntatore alla memoria grezza, non costruita in cui vogliamo costruire un oggetto di tipo Te il secondo è un valore di tipo di elemento per inizializzare quell'oggetto. Quindi viene invocato il costruttore di copia:

struct Foo {
    Foo(int, int) { cout << "Foo(int, int)" << endl; }
    /*explicit*/ Foo(int) { cout << "Foo(int)" << endl; }
    Foo(const Foo&) { cout << "Foo(const Foo&)" << endl; }
};

int main(int argc, char* argv[]) {


    allocator<Foo> a;
    Foo* const p = a.allocate(200, NULL); // second parameter is required on C++98 but on C++11 it is optional
//  Foo* const p = a.allocate(200); // works fine on C++11 but not on C++98

    a.construct(p, 5, 7); // works on C++ 11 and up but not C++98
    a.construct(p, 10);// works on both
    a.destroy(p);
    a.destroy(p + 1);
    a.deallocate(p, 200);



    std::cout << std::endl;
}
  • Perché su C ++ 98 a.construct(p, 10)chiamando il costruttore di copie ma su C ++ 11 e versioni successive si chiama solo il costruttore che accetta un numero intero?

  • Questo significa in C ++ 11 a causa di qualche ottimizzazione Copy-elisione anche se il costruttore Foo(int)è explicitlavori su tale chiamata: a.construct(p, 5)opere in C ++ 11, anche il costruttore è explicitquello che sono sicuro è che non funziona su C ++ 98 se Foo(int)lo è explicit.

  • In tal caso, se compilo quell'istruzione con una sorta di disabilitazione copy-elisiondell'ottimizzazione, il compilatore fallirà? Grazie.


3
Risposta breve: fino a C ++ 11, non vi era alcun ritorno perfetto . Dettagli forniti di seguito da @flyx. Si noti che non è coinvolta alcuna elisione della copia (nessun valore di passaggio o valore di ritorno).
Daniel Langr,

Risposte:


13

Questo perché la dichiarazione di è construct cambiata in C ++ 11 :

void construct( pointer p, const_reference val );  (1)  (until C++11)
template< class U, class... Args >
void construct( U* p, Args&&... args );            (2)  (since C++11)

La prima dichiarazione chiama il costruttore della copia, mentre la seconda dichiarazione chiama un costruttore che corrisponde alla lista di argomenti fornita. Questo potrebbe essere il costruttore della copia, ma anche un altro costruttore come hai visto nel tuo codice.

a.construct(p, 10)chiama il costruttore della copia in C ++ 98 perché 10viene implicitamente convertito in Footramite il Foo(int)costruttore. Questa conversione non è necessaria in C ++ 11 poiché esiste un costruttore corrispondente che accetta un int(esattamente il costruttore utilizzato per la conversione in C ++ 98). Questo è anche il motivo per cui il codice non funziona in C ++ 98 quando si aggiunge explicit- non può convertirlo 10in un Fooallora.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.