2016-04-15 3 views
0

Может ли кто-нибудь объяснить мне причину, почему в этом коде определены MyClass (const MyClass & src) { m_X = src . m_X; }? Без этой строки кода он отлично работает и дает такой же результат, который в этом случае равен 32. В чем разница между им и не в нем? Я прочитал, что конструктор копирования создается автоматически, но когда вы определили указатель в классе, вы должны определить его, но я не понимаю, почему в этом случае.Копирование конструктора путаницы

код ниже:

#include <iostream> 
using namespace std; 

class MyClass 
{ 
public: 
    MyClass (int x) : m_X (new int (x)) {} 
    MyClass (const MyClass &src) 
    { 
     m_X = src.m_X; 
    } 

    void print (void) const 
    { 
     cout << *m_X; 
    } 

private: 
    int * m_X; 
}; 


int main (void) 
{ 
    MyClass a (32), c = a; 
    c.print(); 

    return 0; 
} 

ответ

1

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

MyClass (const MyClass & src) : m_X(new int(*src.m_X) {} 

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

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

2

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

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

2

Проблема с компилятором, созданным одним (и вашим), заключается в том, что он копирует указатель. Теперь у вас есть два указателя c.m_x и a.m_x оба указателя на один и тот же кусок выделенного объекта. Кому это принадлежит? Что произойдет, если вы удалите a, он должен удалить выделенную память (вы неправильно это сделаете), но c все еще работает на нем.

По этой причине std::shared_ptr. Он предназначен для этого случая, он делает Right Thing By Magic

Заменить int * m_X на std::shared_ptr<int> m_X