Как правильно применить правило 5 (или ноль?) К классу, содержащему вектор пользовательских объектов со строками - PullRequest
0 голосов
/ 26 апреля 2019

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

namespace Excel {

class Cell
{
public:
  // ctors
  Cell() = default;
  Cell(std::string val) : m_val(val) {};
  // because I have a custom constructor, I assume I need to also
  // define copy constructors, move constructors, and a destructor.
  // If I don't my understanding is that the private string member 
  // will always be copied instead of moved when Cell is replicated 
  // (due to expansion of any vector in which it is stored)? Or will 
  // it be copied, anyways (so it doesn't matter or I could just 
  // define them as default)

  value() const { return m_val; }; // getter (no setter)
private:
  std::string m_val;
}

class Row
{
public:
  // ctors
  Row() = default;
  Row(int cellCountHint) : m_rowData(cellCountHint) {}

  // copy ctors (presumably defaults will copy private vector member)
  Row(const Row&) = default;
  Row& operator=(Row const&) = default;

  // move ctors (presumably defaults will move private vector member)
  Row(Row&& rhs) = default;
  Row& operator=(Row&& rhs) = default;

  // and if I want to append to internal vector, might I get performance
  // gains by moving in lieu of copying, since Cells contain strings of
  // arbitrary length/size?
  void append(Cell cell) { m_rowData.push_back(cell); };
  void append(Cell &&cell) { m_rowData.push_back(std::move(cell)); };
private:
  std::vector<Cell> m_rowData;
}

}

И так далее:

  • Класс рабочего листа будет содержать вектор строк
  • Рабочая книгакласс будет содержать вектор Worksheets

Я не чувствовал необходимости реализовывать эти два последних для MWE, так как они эффективно дублируют Row (мое предположение , если они будут идентичныдизайн Row).

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

1 Ответ

4 голосов
/ 26 апреля 2019

Если класс имеет дело с владением ресурсом, то этот класс должен ТОЛЬКО управлять этим ресурсом.Это не должно делать ничего другого.В этом случае определите все 5 (правило 5).

Иначе, классу не нужно реализовывать ни одно из 5 (правило 0).

Просто так.


Теперь я видел, как эти правила сформулированы следующим образом: если класс определяет любой из 5, то он должен определять все из них.Ну да и нет.Причиной этого является то, что: если класс определяет любой из 5, то это сильный индикатор того, что класс должен управлять ресурсом, и в этом случае он должен определить все 5. Так, например, если вы определяете деструктор для освобожденияресурс, то класс находится в первой категории и должен реализовывать все 5, но если вы определяете деструктор просто для добавления некоторых операторов отладки или для ведения журнала, или потому что класс полиморфен, тогда класс не первая категория, поэтому вы нене нужно определять все 5.

Если ваш класс относится ко второй категории, и вы определяете хотя бы одну из 5, то вы должны явно =default остальные из 5. Это потому, что правилакогда неявно объявляются cpy / move ctors / assignments, это немного сложно.Например, определение dtor предотвращает неявное объявление хода ctor & assigment


// because I have a custom constructor, I assume I need to also
// define copy constructors, move constructors, and a destructor.

Неверно.Пользовательский конструктор не является частью 5.


Все ваши классы должны следовать правилу 0, поскольку ни один из них не управляет ресурсами.

На самом деле это довольно редко для пользователяКод необходимо реализовать правило 5 класса.Обычно это реализовано в библиотеке.Таким образом, как пользователь, почти всегда по правилу 0.


Коры / назначения копирования / перемещения по умолчанию делают ожидаемую вещь: копии копируют каждого члена, а перемещения -переместить каждого члена.Что ж, при наличии элементов, которые не являются подвижными, или у которых есть только некоторые из 5, или у которых есть некоторые из 5 удаленных, тогда правила становятся немного более сложными, но нет неожиданного поведения.По умолчанию это хорошо.

...