2012-08-17 9 views
14

Tengo una clase como la siguiente.Error con el constructor de copia/operador de asignación para una clase que tiene la variable de miembro std :: atomic

#include <atomic> 

static const long myValue = 0; 

class Sequence 
{ 

public: 

    Sequence(long initial_value = myValue) : value_(initial_value) {} 


private: 

    std::atomic<long> value_; 
}; 

int main() 
{ 
     Sequence firstSequence; 
     Sequence secondSequence = firstSequence; 
     return 0; 
} 

estoy consiguiendo error de compilación como esta,

test.cpp:21:36: error: use of deleted function ‘Sequence::Sequence(const Sequence&)’ 
test.cpp:5:7: error: ‘Sequence::Sequence(const Sequence&)’ is implicitly deleted because the default definition would be ill-formed: 
test.cpp:5:7: error: use of deleted function ‘std::atomic<long int>::atomic(const std::atomic<long int>&)’ 

¿Es que el constructor de copia por defecto y asignación opertaor no funcionan en este caso?

PS: Estoy utilizando la versión de gcc 4.6.3

Respuesta

14

No se puede copiar atomics con un constructor de copia estándar, ya que todas las cargas y las tiendas deben realizarse de forma explícita. Deberá escribir su propio constructor de copia para Sequence que inicialice el formulario value_(rhs.value_.load()) (posiblemente con un orden de memoria más relajado).

+0

¿Se puede editar y agregar un ejemplo de código de compilación? No puedo resolver este problema, lo he intentado: 'Secuencia & operator = (const Sequence & other) {value_ = other.value_.load(); devuelve * esto; } ' –

+0

@VictorLamoine: No tengo idea de lo que hizo, pero el enfoque general [funciona] (https://wandbox.org/permlink/ZsHPDqhrIiybq7qf). –

+1

Para obtener más información sobre cómo escribir un constructor de copia (con 'seq_cst' predeterminado para cargar el origen, pero luego evitar el costo de un almacén atómico en el objeto en construcción), vea [Copiar constructor para las clases con miembro atómico ] (https://stackoverflow.com/questions/19961043/copy-constructor-for-classes-with-atomic-member/46045691#46045691). Asegúrese de que esto sea realmente lo que desea implementar; la copia alrededor de átomos suele ser contraria a su propósito como estado compartido. –

5

Debido a que no hay una función std::atomic<long int>::atomic(const std::atomic<long int>&), no hay manera para que el compilador crea un constructor de copia por defecto para la clase Sequence. Si necesita un constructor de copia para esa clase (y lo hace si quiere que Sequence secondSequence = firstSequence; funcione), entonces necesita escribir uno.

Este comportamiento es requerido por la norma:

Los tipos integrales y dirección atómicas se enumeran a continuación. Estos tipos deben tener un diseño estándar. Deberán tener un constructor predeterminado trivial, un constructor de valor explícito constexpr, un constructor de copia eliminada, un operador de asignación de copia eliminado y un destructor trivial. Estos tipos soportarán la sintaxis de inicialización agregada.

6

Atomic ha eliminado copy-ctor. Así que se eliminan los copy/move-ctors en su clase.

n3337 12.8/11

Un constructor de copia/movimiento implícitamente declarado es un miembro público en línea de su clase. Una copia omitido/ constructor movimiento para una clase X se define como eliminado (8.4.3) si X tiene:

- un miembro de datos no estático de tipo de clase M (o serie de los mismos) que no se puede copiar/movido porque resolución de sobrecarga (13.3), tal como se aplica a los correspondientes al constructor de M, da lugar a una ambigüedad o una función que se suprime o inaccesibles desde el constructor default,

0

supongo que la elección para eliminar el el constructor de copias en el estándar fue por dos razones:

  • se requiere un par de carga/almacenamiento en general. ¿Hay alguna manera de hacer cumplir que esto se haría cuando no controlas a los llamadores de std :: atomic?

  • ¿Qué hacer si std :: atomic <> tipo que estaba utilizando fue uno para el cual is_lock_free() es falso (es decir, se requiere un mutex en la implementación para ese tipo de entero de tamaño)? ¿Qué semántica de copia utilizas para la inicialización mutex? Un mutex que termina copiado implícitamente necesita ser reinicializado ya que podría ser copiado desafortunadamente en un estado bloqueado. Supongo que std :: mutex también tiene un constructor de copia eliminado debido a esto, y eso empuja el requisito a std :: atomic también.

Cuestiones relacionadas