Deshabilitar el constructor de copia


Tengo una clase:

class SymbolIndexer {
protected:
  SymbolIndexer ( ) { }

public:
  static inline SymbolIndexer & GetUniqueInstance ( ) 
  { 
    static SymbolIndexer uniqueinstance_ ;
    return uniqueinstance_ ; 
  }
};

¿Cómo debo modificarlo para desactivar el código como:

SymbolIndexer symbol_indexer_ = SymbolIndexer::GetUniqueInstance ( );

Y solo permite código como:

SymbolIndexer & ref_symbol_indexer_ = SymbolIndexer::GetUniqueInstance ( );
Author: Humble Debugger, 2011-05-21

3 answers

Puede hacer que el constructor de copia sea privado y no proporcionar ninguna implementación:

private:
    SymbolIndexer(const SymbolIndexer&);

O en C++11, prohibirlo explícitamente:

SymbolIndexer(const SymbolIndexer&) = delete;
 232
Author: R. Martinho Fernandes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-10 13:56:01

Si no le importa la herencia múltiple (no es tan malo, después de todo), puede escribir clase simple con constructor de copia privada y operador de asignación y, además, subclase:

class NonAssignable {
private:
    NonAssignable(NonAssignable const&);
    NonAssignable& operator=(NonAssignable const&);
public:
    NonAssignable() {}
};

class SymbolIndexer: public Indexer, public NonAssignable {
};

Para GCC esto da el siguiente mensaje de error:

test.h: In copy constructor ‘SymbolIndexer::SymbolIndexer(const SymbolIndexer&)’:
test.h: error: ‘NonAssignable::NonAssignable(const NonAssignable&)’ is private

Aunque no estoy muy seguro de que esto funcione en todos los compiladores. Hay una pregunta relacionada, pero sin respuesta todavía.

UPD:

En C++11 también puede escribir NonAssignable class como sigue:

class NonAssignable {
public:
    NonAssignable(NonAssignable const&) = delete;
    NonAssignable& operator=(NonAssignable const&) = delete;
    NonAssignable() {}
};

La palabra clave delete evita que los miembros se construyan por defecto, por lo que no se pueden usar más en los miembros construidos por defecto de una clase derivada. Intentar asignar da el siguiente error en GCC:

test.cpp: error: use of deleted function
          ‘SymbolIndexer& SymbolIndexer::operator=(const SymbolIndexer&)’
test.cpp: note: ‘SymbolIndexer& SymbolIndexer::operator=(const SymbolIndexer&)’
          is implicitly deleted because the default definition would
          be ill-formed:

UPD:

Boost ya tiene una clase solo para el mismo propósito, supongo que incluso se implementa de manera similar. La clase se llama boost::noncopyable y está destinado a ser utilizado como en el siguiente:

#include <boost/core/noncopyable.hpp>

class SymbolIndexer: public Indexer, private boost::noncopyable {
};

Yo recomendaría pegarse a la solución de Boost si su política de proyecto lo permite. Ver también otro boost::noncopyable-pregunta relacionada para más información.

 21
Author: firegurafiku,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:25:51

Haz que SymbolIndexer( const SymbolIndexer& ) sea privado. Si estás asignando a una referencia, no estás copiando.

 4
Author: Aaron Klotz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-20 20:16:29