Конструктор глубокого копирования в C ++ - PullRequest
0 голосов
/ 25 октября 2019

Я хочу построить конструктор копирования Pair(const Pair& other). В качестве аргумента используется ссылка только для чтения на другой Pair. Он должен настроить вновь созданный Pair как «глубокую копию». Но я понятия не имею, как установить целые числа в этих новых местах, которым должны быть присвоены значения в соответствии с целыми числами, на которые указывает другой Pair.

class Pair {
public:
  int *pa,*pb;
  Pair(int a, int b);
  Pair(const Pair & other);
  ~Pair();
};

Pair::Pair(int a, int b){
  pa = new int;
  pb = new int;
  *pa = a;
  *pb = b;
}

Pair::Pair(const Pair & other){
  pa = new int;
  pb = new int;
  *pa = *(other.pa);
  *pb = *(other.pb);
}

Pair::~Pair(){
  delete pa;
  delete pb;
}

int main() {
  Pair p(15,16);
  Pair q(p);
  Pair *hp = new Pair(23,42);
  delete hp;

  std::cout << "If this message is printed,"
    << " at least the program hasn't crashed yet!\n"
    << "But you may want to print other diagnostic messages too." << std::endl;
  return 0;
}

Ответы [ 3 ]

2 голосов
/ 25 октября 2019

Ваш конвертирующий конструктор не присваивает значения int s, которые он выделяет, и он не назначает эти указатели членам класса.

Ваша копия * 1007Конструктор также не присваивает выделенные указатели членам класса. Он также неправильно использует оператор * при доступе к членам other.

Ваш деструктор нуждается в delete членах класса, выделенных конструкторами.

И вам нужно добавить оператор назначения копирования , чтобы правильно завершить Правило 3 .

Попробуйте это:

class Pair {
public:
  int *pa,*pb;
  Pair(int a, int b);
  Pair(const Pair & other);
  ~Pair();
  Pair& operator=(const Pair & other);
};

Pair::Pair(int a, int b){
  pa = new int;
  pb = new int;
  *pa = a;
  *pb = b;

  /* alternatively:
  pa = new int(a);
  pb = new int(b);
  */
}

Pair::Pair(const Pair & other){
  pa = new int;
  pb = new int;
  *pa = *(other.pa);
  *pb = *(other.pb);

  /* alternatively:
  pa = new int(*(other.pa));
  pb = new int(*(other.pb));
  */
}

Pair::~Pair(){
  delete pa;
  delete pb;
}

Pair& Pair::operator=(const Pair & other){
  *pa = *(other.pa);
  *pb = *(other.pb);
  return *this;
}

int main() {
  Pair p(15,16);
  Pair q(p);
  Pair *hp = new Pair(23,42);
  p = *hp;
  delete hp;

  std::cout << "If this message is printed,"
    << " at least the program hasn't crashed yet!\n"
    << "But you may want to print other diagnostic messages too." << std::endl;
  return 0;
}
1 голос
/ 25 октября 2019

Ваш первый конструктор может выглядеть так:

Pair::Pair(int a, int b)
    : pa(new int(a))
    , pb(new int(b))
{
}

И вам не нужно многократно писать сложный код, перенаправляя его в первый конструктор.

Pair::Pair(const Pair & other) 
    : Pair(*other.pa, *other.pb) 
{
}

Другая вещьявляется то, что вы также должны реализовать оператор присваивания. В противном случае ваш код будет очень подвержен ошибкам, если вы случайно сделаете присваивание (как если бы вы имели двойное значение delete, предполагая, что ваш деструктор правильно реализован.

Сказав это, ваш деструктор должен быть:

Pair::~Pair()
{
    delete pa;
    delete pb;
}

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

// Inside class declaration
Pair &operator=(const Pair &other);

// With other definitions.
Pair &Pair::operator=(const Pair &other)
{
    *pa = *other.pa;
    *pb = *other.pb;
    return *this;
}

Если вам действительно нужны указатели, тогда я бы порекомендовал вам использовать std::unique_ptr.

В вашем классе объявление становится std::unique_ptr<int> pa; и похоже на pb. В этот момент ваш деструктор станет пустым. Оставшийся код может остаться прежним.

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

0 голосов
/ 25 октября 2019

Ваш конструктор init и конструктор копирования могут иметь некоторые ошибки.

Конструктор init должен быть:

Pair::Pair(int a, int b){
  pa = new int;
  pb = new int;
  *pa = a;
  *pb = b;
}

И конструктор копирования должен быть:

Pair::Pair(const Pair & other){
  pa = new int;
  pb = new int;
  *pa = *(other.pa);
  *pb = *(other.pb);
}
...