2015-01-28 14 views
13

Si prega di considerare il seguente codice:diverso comportamento di C++ 11-elenco di inizializzazione

class A { 
private: 
    std::string s; 
public: 
    A() = delete; 
    A(const A&) = delete; 
    A(A&&) = delete; 
    A(const std::string &a) : s(a) {} 
}; 

Ora, vorrei inizializzare un array di A inizializzazione lista usando. g ++ (4.9.1) potrebbe costruire con successo il seguente codice:

int main() { 
    A arr[2] = {{"a"}, {"b"}}; 
    return 0; 
} 

Ma, non è riuscito per il seguente codice:

class Aggr { 
private: 
    A arr[2]; 
public: 
    Aggr() : arr{{"a"}, {"b"}} {} 
}; 

I messaggi di errore sono,

test.cc: In constructor ‘Aggr::Aggr()’: 
test.cc:22:28: error: use of deleted function ‘A::A(A&&)’ 
    Aggr() : arr{{"a"}, {"b"}} {} 
          ^   
test.cc:11:3: note: declared here 
    A(A&&) = delete; 
^

Detto , un inizializzatore di elenchi tenta di chiamare un costruttore di mosse per inizializzare un array all'interno di una classe. Quel codice, tuttavia, è stato creato con successo da clang v3.5 senza alcun avviso. Quindi, vorrei sapere cosa C++ 11 (o versione successiva) specifica le regole rispetto all'inizializzazione della lista. Grazie in anticipo.

+0

Perché è "A &&'? – ZivS

+0

@ZivS un riferimento di valore – bolov

+3

probabilmente rilevante per il problema: http://stackoverflow.com/questions/26685551/how-to-initialize-array-of-classes-with-deleted-copy-constructor-c11 – marcinj

risposta

2

Leggendo ancora e ancora lo standard, penso che questo sia un bug.

Cosa dice lo standard?

8.5.1/2: Quando un aggregato viene inizializzato da una lista di inizializzazione, come specificato in 8.5.4, gli elementi della lista di inizializzazione sono presi come inizializzatori per i membri dell'aggregato, in aumento di pedice o ordine di membro. Ogni membro è inizializzato dalla copia dalla clausola initializer corrispondente .

Si spiega che:

8,5/14: (...) si chiama copia-inizializzazione. [Nota: l'inizializzazione della copia può richiedere uno spostamento (12.8). -end note]

Ma non ho trovato prove in 12.8 che nel tuo caso specifico sarebbe necessaria una mossa.

8.5.4/3 In caso contrario, se T è un tipo di classe, i costruttori sono considerati. Se T ha un costruttore inizializzatore-lista, l'argomento lista consiste dell'elenco inizializzatore come un singolo argomento; altrimenti, l'elenco degli argomenti è costituito dagli elementi dell'elenco di inizializzazione. I costruttori applicabili vengono enumerati e viene selezionato il migliore tramite la risoluzione di sovraccarico (13.3).

Quindi in linea di principio il codice dovrebbe funzionare!

È un errore? Provare il modo sperimentale

Ho commentato l'eliminazione del costruttore di spostamenti, per beneficiare del costruttore di spostamenti impliciti.Stranamente, ho quindi ricevuto il seguente messaggio di errore:

Compilation error time: 0 memory: 3232 signal:0 

prog.cpp: In constructor 'Aggr::Aggr()': 
prog.cpp:19:28: error: use of deleted function 'A::A(const A&)' 
    Aggr() : arr{{"a"}, {"b"}} {} 
          ^
prog.cpp:10:3: note: declared here 
    A(const A&) = delete 

Così ora si lamenta di un costruttore di copie mancante!

Ancora più strano, ho quindi fornito il mio costruttore di mosse invece dell'implicito: qui ha compilato il codice con successo !!

Finalmente disponibile sia una copia e una mossa e aggiunti alcuni tracciamento:

class A { 
private: 
    std::string s; 
public: 
    A() = delete; 
    A(const A&) { std::cout<<"copy\n";} //= delete; 
    A(A&&) { std::cout<<"move\n";} //= delete; 
    A(const std::string &a) : s(a) { std::cout<<"string ctor\n";} 
}; 

E quando si crea un oggetto Aggr, visualizza solo:

string ctor 
string ctor 

dimostrando che l'elemento di matrice è inizializzato forma il costruttore di stringhe usando la copia elision come ci saremmo aspettati.

Tutti questi test sono stati eseguiti con gcc-9.4.2 su ideone con opzione C++ 14.

Conclusione

Il fatto che lo stesso codice non riesce a compilare con implicita mossa ctor e riesce con una mossa ctor definito dall'utente appare molto sul serio come un insetto.

Il fatto che il costruttore di movimento non venga utilizzato quando è disponibile rafforza questa impressione.

Di conseguenza, ho segnalato this bug.

+0

Bella risposta e grazie per segnalare questo errore. – Destructor

Problemi correlati