Копировать конструктор с указателями

Недавно я обнаружил, что когда у меня есть указатели внутри класса, мне нужно указать конструктор Copy.

Чтобы узнать, что я сделал следующий простой код. Он компилируется, но дает мне ошибку выполнения при выполнении конструктора копирования.

Я пытаюсь скопировать только значение из указателя скопированного объекта, но избегая назначения того же адреса.

Итак, что здесь не так?

    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;
    }

Я буду использовать эту концепцию для других классов с большим количеством указателей в ней, где мне нужно скопировать все значения с объекта на другой. Копирование первоначально необходимо для этого кода, поэтому я хотел бы сохранить возможность копирования (я не буду скрывать конструктор копирования как закрытый).

Кроме того, реальный класс, который мне нужно реализовать, имеет 10 указателей, и он может меняться со временем. Разве нет более умного способа иметь конструктор глубоких копий на С++?...

Ответ 1

С помощью инструкции int* pointer вы только что указали указатель, но не выделили какую-либо память. Сначала вы должны указать на правильное расположение памяти, выделив некоторую память следующим образом: int* pointer = new int. Затем в конструкторе копирования вы должны выделить память для скопированного объекта. Кроме того, не забудьте освободить память, используя delete в деструкторе.

Надеюсь, этот пример поможет:

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;
}

Ответ 2

Недавно я обнаружил, что когда я иметь указатели внутри класса, мне нужно для указания конструктора копирования.

Это не совсем так. Когда у вас есть указатели в вашем классе и выделяете память с помощью new, вам придется беспокоиться о конструкторе копирования. Кроме того, не забудьте оператор присваивания и деструктор. Вы должны удалить выделенную память, используя delete.

Он назвал Закон Большой тройки.

Пример:

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

Ответ 3

Если вы хотите сделать глубокую копию, вы, конечно же, должны также выделить новую память для хранения значений. Если у оригинала есть указатель на int, и вы не хотите, чтобы копия использовала одно и то же значение указателя, вы должны выделить новую память для хранения int и затем скопировать туда значение.

Ваш пример не очень ясен, он не показывает реализацию вашего конструктора копирования или как инициализируется член pointer.

Ответ 4

если он имеет указатель на обычный тип, то

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

если он имеет указатель на некоторый базовый класс, то

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

Клонирование - это реализация шаблона прототипа

Не забудьте удалить указатель в деструкторе

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

Чтобы исправить ваш пример

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

Ответ 5

Ваша проблема в этой строке прямо здесь:

    *pointer = a;

Все, что обычно происходит в вашем конструкторе по умолчанию, еще не произошло, включая выделение памяти для *pointer.

Исправление состоит в том, чтобы выделить память для целого числа. Вы можете использовать malloc и друзей или new для этого, но убедитесь, что это тот же метод, который вы используете в своем конструкторе по умолчанию, потому что вы получаете только один деструктор, а вызовы должны совпадать.

Ответ 6

Если членская (мелкая) копия в порядке, то вам не нужно ничего делать. Если вам нужна глубокая копия, вам необходимо выделить новое хранилище для копий всех членов.

Ответ 7

Недавно я обнаружил, что когда я иметь указатели внутри класса, мне нужно для указания конструктора копирования

Чаще всего это хорошая идея просто отключить его, объявив его (и оператор-ассистент) частным и не реализуя его.

Ответ 8

При написании Copy Constructor вы должны выделить память для всех членов. В вашем случае:

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

Оператор = как-то подобен, но без выделения памяти.

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

Ответ 9

Чаще всего, если вам нужно написать конструктор копирования или оператор присваивания, вы делаете что-то неправильно. Оставьте конструкторы копирования и операторы присваивания исполнителям стандартной библиотеки. Составьте свои классы уже скопируемых и присваиваемых элементов, и вам не придется писать свои собственные.

Например, возможно, что int * member должен быть std::vector.

Если вы не можете сделать класс по умолчанию скопированным/назначаемым, возможно, вы можете сделать его не копируемым/назначаемым, объявив, но не реализуя, частный конструктор копирования и оператор присваивания.

Только если ни одно из вышеперечисленных вариантов не является выполнимым, если вы реализуете свой собственный конструктор копий или оператор присваивания.