2014-09-30 11 views
5

Sebbene abbia lavorato per diversi anni con C#, fare qualcosa in C++ è ancora difficile per me. Approvo pienamente l'uso di puntatori intelligenti, ma ora mi trovo di fronte al seguente puzzleErrore durante la dichiarazione di una classe con std :: vector di struct contenenti std :: unique_ptr

Ho una struttura Foo, ad es.

struct Foo 
{ 
    Foo(std::unique_ptr<Bar> bar) : m_myBar(std::move(bar)) {} 

private: 
    std::unique_ptr<Bar> m_myBar;   
}; 

in una classe diversa, voglio avere un vettore che contiene le istanze di Foo, ma la seguente riga

std::vector<Foo> m_Foos; 

rendimenti errori di compilazione dicendo che il costruttore di copia viene eliminata. Nel thread SO "Why can I not push_back a unique_ptr into a vector?" viene fornita una spiegazione e un rimedio. Tuttavia, la domanda riguarda un vettore di puntatori univoci, mentre io ho un vettore di strutture contenente un puntatore univoco. La soluzione suggerita è usare la semantica del movimento, ma come si applica nella mia situazione? O dovrei fare qualcos'altro?

+0

Si sta utilizzando Visual Studio? – Angew

+0

No, sto usando Qt Creator 3.1.2 basato su Qt 5.3.1 con mingw32-make.exe. È importante? – SimonAx

+0

Quale compilatore? Presumo mingw gcc, che dovrebbe essere OK. Il compilatore di Visual Studio non può generare automaticamente i sensori di movimento. Ma la stessa linea vettoriale non sta causando l'errore, vedi il link nella mia risposta. È forse racchiuso in una classe, che influenzerebbe il copyctor di quella classe? IOW, per favore pubblica un [MCVE] (http://stackoverflow.com/help/mcve). – Angew

risposta

4

Come dici tu, m_Foos è in realtà un membro di dati di un'altra classe (lo chiamerò FooHolder). Se non hai fornito un costruttore di copia per FooHolder, il compilatore ne genererà uno automaticamente. Il costruttore di copia chiamerà i costruttori di copia di tutti i membri di dati di FooHolder, incluso m_Foos. Naturalmente, il costruttore di copie di std::vector<Foo> contiene un errore di compilazione, dal momento che Foo non è copiabile. Questo è probabilmente il motivo per cui stai ricevendo l'errore.

È necessario fornire un costruttore di copia appropriato per FooHolder, se è possibile e desidera che tale classe sia copiabile. In caso contrario, si può semplicemente dichiarare un costruttore di movimento (possibilmente in default), che renderà il costruttore di copia eliminata:

struct FooHolder 
{ 
    FooHolder(FooHolder&&) = default; 

private: 
    std::vector<Foo> m_Foos; 
}; 
+0

L'OP può ancora avere l'errore durante il tentativo di 'push_back' lvalue di' Foo' poichè 'Foo' non è copy-constructible, vale la pena menzionare –

+0

@PiotrS. L'OP sostiene che l'errore è venuto dalla definizione del vettore - non è così. E la risposta ha riguardato anche lo spostamento della struttura stessa. – Angew

+0

leggi il commento sotto la risposta di Kerrek –

1

Non è possibile copiare puntatori univoci. Si può solo spostare loro:

Foo(std::unique_ptr<Bar> bar) : m_myBar(std::move(bar)) {} 
//          ^^^^^^^^^^^^^^ 
+0

@angew e Kerrek. Grazie per aver sottolineato che non riesco a digitare: -s Nella mia domanda iniziale ho dimenticato di includere che io uso std :: move, che hai menzionato entrambi. Ho aggiornato la mia domanda originale per riflettere questo. Quando si cancella la linea std :: vector m_Foos, il programma si compila e posso anche costruire oggetti Foo, quindi sono abbastanza sicuro che il vettore sta causando il problema. – SimonAx

+0

@SimonAx: quali operazioni eseguite sul vettore? e provi a copiare quell'altra classe con 'std :: vector'? –

+0

@PiotrS. Non ho ancora eseguito alcuna operazione sul vettore. Prima di andare oltre spingendo indietro elementi volevo verificare che il programma fosse compilato e non lo fosse. – SimonAx

Problemi correlati