Pergunta

Tenho recentemente descobriu que quando eu tenho ponteiros dentro de uma classe, eu preciso especificar um construtor de cópia.

Para saber isso, eu fiz o seguinte código simples. Ele compila, mas dá-me tempo de execução de erro ao executar o construtor de cópia.

Eu estou tentando copiar apenas o valor do ponteiro do objeto copiado, mas evitando atribuir o mesmo endereço.

Então, o que está errado aqui?

    class TRY{
        public:
        TRY();
    ~TRY();
        TRY(TRY const &);

        int *pointer;

        void setPointer(int);
    };


    void TRY::setPointer(int a){
        *pointer = a;

        return;
    }


    TRY::TRY(){}


    TRY::~TRY(){}


    TRY::TRY(TRY const & copyTRY){
        int a = *copyTRY.pointer;
        *pointer = a;
    }



    int main(){

        TRY a;
        a.setPointer(5);

        TRY b = a;

        b.setPointer(8);

        cout << "Address of object a = " << &a << endl;
        cout << "Address of object b = " << &b << endl;

        cout << "Address of a.pointer = " << a.pointer << endl;
        cout << "Address of b.pointer = " << b.pointer << endl;

        cout << "Value in a.pointer = " << *a.pointer << endl;
        cout << "Value in b.pointer = " << *b.pointer << endl;

        return 0;
    }

Eu vou estar usando esse conceito para outras classes com lotes de ponteiros em que, onde eu preciso para copiar todos os valores a partir de objeto para o outro. Copiar é inicialmente necessária para este código, então eu gostaria de manter a possibilidade de cópia (não vou estar escondendo o construtor de cópia como privado).

Além disso, a verdadeira classe Eu preciso implementar tem como 10 pontos, e pode estar mudando com o tempo. não há uma maneira um pouco mais inteligente para ter um construtor cópia profunda em C ++? ...

Foi útil?

Solução

Com a int* pointer declaração que você acabou de definir um ponteiro, mas não atribuiu qualquer memória. Primeiro você deve fazê-lo apontar para uma localização de memória adequada através da atribuição de alguma memória assim: int* pointer = new int. Em seguida, no construtor de cópia novamente você tem que alocar a memória para o objeto copiado. Além disso, não se esqueça de liberar a memória usando exclusão no processo de destruição.

Espero que este exemplo ajuda:

class B
{

public:
    B();
    B(const B& b);
    ~B();
    void setVal(int val);

private:
    int* m_p;
};

B::B() 
{
    //Allocate the memory to hold an int
    m_p = new int;

    *m_p = 0;
}

B::B(const B& b)
{
    //Allocate the memory first
    m_p = new int;

    //Then copy the value from the passed object
    *m_p = *b.m_p;
}

B::~B()
{

    //Release the memory allocated
    delete m_p;
    m_p = NULL;
}

void B::setVal(int val)
{
    *m_p = val;
}

Outras dicas

Eu descobri recentemente que quando eu ter ponteiros dentro de uma classe, eu preciso para especificar um construtor de cópia.

Não é completamente verdade. Quando você tem ponteiros em sua classe e alocar a memória usando new então você tem que se preocupar com construtor de cópia. Além disso, não se esqueça o operador de atribuição e destruidor. Você tem que apagar a memória alocada usando delete.

É chamado Of The Big Three .

Exemplo:

  ~Matrix();  //Destructor
  Matrix(const Matrix& m); //Copy constructor
  Matrix& operator= (const Matrix& m); //Assignment operator

Se você quer fazer uma cópia profunda, você, claro, também deve alocar nova memória para armazenar os valores. Se o original tem um ponteiro para um int, e você não quer que a cópia para usar o mesmo valor do ponteiro, você deve alocar nova memória para armazenar um int, e depois copiar o valor lá.

Seu exemplo não é muito clara, ele não mostra a implementação de seu construtor de cópia, ou como o membro pointer é inicializado.

Eu descobri recentemente que quando eu ter ponteiros dentro de uma classe, eu preciso para especificar um construtor de cópia

Mais frequentemente do que não é uma boa idéia para simplesmente desativá-lo, declarando-o (e o operador assigment) privada e não implementá-lo.

se ele tem um ponteiro para um tipo regular, então

A::A(const A& a):
  pointer_( new int( *a.pointer_ ) )
{
}

se ele tem um ponteiro para uma classe base, em seguida

A::A(const &a ):
  pointer_( a.pointer_->clone() )
{
}

Clone é uma implementação de um protótipo padrão

Não se esqueça de apagar o ponteiro no processo de destruição

A::~A()
{
    delete pointer_;
}

Para corrigir o seu exemplo

TRY::TRY(TRY const & copyTRY){
    int a = *copyTRY.pointer;
    pointer = new int(a);
}

Seu problema é nesta linha aqui:

    *pointer = a;

Todas as coisas que normalmente acontece em seu construtor padrão ainda não aconteceu, incluindo a alocação de memória para *pointer.

A correção é para alocar memória para um número inteiro. Você pode usar malloc e amigos ou new para isso, mas ter certeza que é o mesmo método que você usar em seu construtor padrão, porque você só tem uma destructor, e as chamadas têm que combinar.

Se um (rasa) cópia membro-wise é bom, então você não tem que fazer nada. Se você quiser uma cópia profunda, você tem que alocar novo armazenamento para cópias de todos os membros.

Ao escrever um construtor de cópia, você deve alocar memória para todos os membros. No seu caso:

TRY::TRY(TRY const & copyTRY){
    pointer = new int(*(copyTry.pointer));
}

Operador = é de alguma forma semelhante, mas sem alocação de memória.

TRY& operator=(TRY const& otherTRY){
      this->a  = *(otherTry.pointer)
      return *this
}

Na maioria das vezes, se você precisa escrever um operador de construtor de cópia ou tarefa que você está fazendo algo errado. Deixar os construtores de cópia e operadores de atribuição para os implementadores da biblioteca padrão. Compor suas classes de elementos já copiáveis ??e atribuíveis e você não terá que escrever o seu próprio.

Por exemplo, talvez isso int * membro deve ser um std :: vector vez.

Se você não pode fazer a copyable padrão de classe / atribuível, talvez você pode torná-lo não copiável / atribuível ao declarar, mas não de execução, um construtor de cópia e atribuição operador privado.

Apenas se nenhuma das opções acima são viáveis ??se você implementar seu próprio construtor de cópia ou cessão operador.

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