2015-03-29 20 views
6

Ho un class A con una variabile membro _atomicVar di tipo std::atomic<int>.
errore C2280: tentativo di fare riferimento a una funzione cancellata (atomico <int>)

#include <atomic> 

class A 
{ 
public: 
    A(); 
    ~A(); 

private: 
    std::atomic<int> _atomicVar; 
}; 

Se io costruisco il progetto ottengo il seguente errore:

error C2280: 'std::atomic<int>::atomic(const std::atomic<int> &)' : attempting to reference a deleted function 

Sono principalmente uno sviluppatore C# in modo da non so ogni dettaglio del C++ (ancora). Non so dove io uso la copia c'tor di atomic<int>.
Ho anche tentato di inizializzare _atomicVar:

std::atomic<int> _atomicVar { 0 }; 

... ma che non ha funzionato.
Mi aspetto che _atomicVar (senza inizializzazione esplicita) venga inizializzato con il valore predefinito per int.
Puoi dirmi perché si verifica questo errore?

+0

Sembra che tu stia utilizzando Visual Studio. Quale versione? Anche su quale riga di codice ottieni l'errore? –

+2

È il tuo intero codice? Forse stai copiando oggetti 'A'? Forse usi un contenitore che richiede elementi 'CopyConstructible'? – zch

+2

Semplicemente non definire il costruttore di copie è una ragione sufficiente per questo.Quando definisci i tipi, che contengono membri 'atomic', devi definire esplicitamente una semantica valida per tutte le operazioni implicite, che possono essere eseguite o inserite dal compilatore. –

risposta

14

Ecco perché il costruttore di copie di std::atomic è eliminato.

Vedere this documentation page.

Poiché non si definisce il costruttore di copie esplicito per A, il compilatore genera quello predefinito, che chiama semplicemente i costruttori di copia per tutti i membri (che non è consentito per std::atomic).

Soluzione:

class A 
{ 
public: 
    A(); 
    A(const A& origin); // add this line 
    ~A(); 
private: 
    std::atomic<int> _atomicVar; 
}; 

A::A(const A& origin) 
: _atomicVar(0) //zero-initialize _atomicVar 
{ 
} 

EDIT

Se vi chiedete, perché atomic tipi non sono copiabile, si consiglia di leggere this question, in particolare risposta accettata. Se si vuole il valore di std::atomic copia, si può fare:

A::A(const A& origin) 
: _atomicVar(origin._atomicVar.load()) 
{ 
} 

Ma tenere a mente, che questa operazione in sé non sarà un uno atomica (e, per la maggior parte le logiche, privo di significato).

Inoltre, è anche possibile definire un operatore di assegnazione esplicito (ricordare circa Rule of Three).

L'opzione migliore per il corretto comportamento del programma sarebbe l'eliminazione di questi due metodi:

class A 
{ 
public: 
    A(); 
    A(const A&) = delete; 
    ~A(); 

    A& operator=(const A&) = delete; 

private: 
    std::atomic<int> _atomicVar; 
}; 

Se il compilatore non supporta questo (ad esempio ogni VC prima VC12), li dichiarano come privato e non fornire un corpo:

class A 
{ 
public: 
    A(); 
    ~A(); 

private: 
    //do not define these two 
    A(const A&); 
    A& operator=(const A&); 

private: 
    std::atomic<int> _atomicVar; 
}; 
+3

Ehm Non lo farei: ora la semantica della copia di 'A' è rotta. Preferirei invece "cancellare" il costruttore di copie di A'. –

+1

Sì, hai ragione. Stavo già aggiornando la mia risposta quando hai scritto questo. –

+0

Grazie @MateuszGrzejek questo mi ha davvero aiutato, ho una classe che è stata istanzializzata usando un shared_ptr, e la classe stessa conteneva un unique_ptr per una dichiarazione forward, non ho capito l'errore che stavo ottenendo all'inizio dato che ho fornito un default distruttore necessario per usare una dichiarazione forward in un unique_ptr, dopo averlo letto e creato un costruttore di copia aggiuntivo nella classe per impostare il nullptr unique_ptr fino a quando è stato chiamato il costruttore corretto, il mio codice ha funzionato, quindi grazie per una buona risposta aiutato molto (= – daniel

Problemi correlati