Pergunta

dizer que tenho uma struct "s" com uma variável de membro do ponteiro int "i". I alocar memória no heap for i in o construtor padrão de s. Mais tarde, em alguma outra parte do código que eu passar uma instância de s por valor para alguma função. Estou fazendo uma rasa copiar aqui? Suponha que eu não implementar nenhum construtor de cópia ou operadores de atribuição ou qualquer coisa para s ... apenas o construtor padrão.

Foi útil?

Solução

Para acompanhar o que @ [don.neufeld.myopenid.com] disse, não é só uma cópia superficial, mas é ou (a sua escolha) um vazamento de memória ou um apontador pendente.

// memory leak (note that the pointer is never deleted)
class A
{
  B *_b;
  public:
  A()
  : _b(new B)
  {
  }
};

// dangling ptr (who deletes the instance?)
class A
{
  B *_b;
  public:
  A()
  ... (same as above)

  ~A()
  {
    delete _b;
  }
};

Para resolver isso, existem vários métodos.

Sempre implementar um construtor de cópia e operador = em classes que usam ponteiros de memória matérias.

class A
{
  B *_b;
  public:
  A()
  ... (same as above)

  ~A()
  ...

  A(const A &rhs)
  : _b(new B(rhs._b))
  {
  }

  A &operator=(const A &rhs)
  {
    B *b=new B(rhs._b);
    delete _b;
    _b=b;
    return *this;
};

É desnecessário dizer que esta é uma grande dor e há algumas sutilezas para obter direito. Eu não estou nem totalmente certo de que eu fiz isso aqui e eu fiz isso algumas vezes. Não se esqueça que você tem que copiar todos os membros - se você adicionar alguns novos, mais tarde, não se esqueça de adicioná-los em demasiado

Faça o construtor de cópia e operador = privado em sua classe. Esta é a "fechar a porta" solução. É simples e eficaz, mas às vezes super-protetor.

class A : public boost::noncopyable
{
  ...
};

Nunca use ponteiros crus. Esta é simples e eficaz. Há muitas opções aqui:

  • Use classes de cordas em vez de ponteiros de char cru
  • Use std :: auto_ptr, boost :: shared_ptr, boost :: scoped_ptr etc

Exemplo:

// uses shared_ptr - note that you don't need a copy constructor or op= - 
// shared_ptr uses reference counting so the _b instance is shared and only
// deleted when the last reference is gone - admire the simplicity!
// it is almost exactly the same as the "memory leak" version, but there is no leak
class A
{
  boost::shared_ptr<B> _b;
  public:
  A()
  : _b(new B)
  {
  }
};

Outras dicas

Sim, isso é uma cópia superficial. Agora você tem duas cópias de s (um no chamador, um na pilha como um parâmetro), cada qual contêm um ponteiro para esse mesmo bloco de memória.

Você terá duas cópias da struct s, cada um dos quais terá o seu próprio ponteiro i, mas ambos os ponteiros i terá o mesmo valor apontando para o mesmo endereço na memória - então sim, será uma cópia superficial.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top