Уменьшение дублирования кода между operator= и конструктором копирования

StackOverflow https://stackoverflow.com/questions/1477145

Вопрос

У меня есть класс, для которого требуется конструктор копирования по умолчанию и оператор присваивания (он содержит списки указателей).Существует ли какой-либо общий способ уменьшить дублирование кода между конструктором копирования и оператором присваивания?

Это было полезно?

Решение

Не существует "общего способа" написания пользовательских конструкторов копирования и операторов присваивания, который работал бы во всех случаях.Но есть идиома под названием "копировать и подкачивать".:

 class myclass
 {
    ...
 public:
    myclass(myclass const&);

    void swap(myclass & with);

    myclass& operator=(myclass copy) {
        this->swap(copy);
        return *this;
    }

    ...
};

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

Другие советы

Разложите общий код на закрытую функцию-член.Простой (довольно надуманный) пример:

#include <iostream>

class Test
{
public:
  Test(const char* n)
  {
    name = new char[20];
    strcpy(name, n);
  }

  ~Test()
  {
    delete[] name;
  }

  // Copy constructor
  Test(const Test& t)
  {
    std::cout << "In copy constructor.\n";
    MakeDeepCopy(t);
  }

  // Assignment operator
  const Test& operator=(const Test& t)
  {
    std::cout << "In assignment operator.\n";
    MakeDeepCopy(t);
  }

  const char* get_name() const { return name; }

private:
  // Common function where the actual copying happens.
  void MakeDeepCopy(const Test& t)
  {        
    strcpy(name, t.name);
  }

private:
  char* name;
};

int
main()
{
  Test t("vijay");
  Test t2(t); // Calls copy constructor.
  Test t3(""); 
  t3 = t2; // Calls the assignment operator.

  std::cout << t.get_name() << ", " << t2.get_name() << ", " << t3.get_name() << '\n';

  return 0;
}
My &My::operator = (My temp)  // thanks, sellibitze
{
    swap (*this, temp);
    return *this;
}

и внедрить специализированный std::swap<> (My &, My &).

Как уже указывалось на довольно многих плакатах, имея operator= создать новый объект с конструктором копирования, а затем использовать swap - это обычная техника, используемая для того, чтобы не копировать код в operator =.

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

Защита от исключений

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

Потребление ресурсов

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top