vendredi 26 avril 2019

How to properly apply rule of 5 (or zero?) to a class containing a vector of custom objects with strings

I'm having trouble wrapping my brain around ownership and maximizing performance with moves. Imagine this hypothetical set of classes emulating an Excel workbook.

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

}

And so on:

  • A Worksheet class would contain a vector of Rows
  • A Workbook class would contain a vector of Worksheets

I felt no need to implement these last two for the MWE since they are effectively duplicative of Row (my assumption is they would be identical to the design of Row).

It's confusing to me to understand if it's ok to rely on the defaults or if I should be defining my own move constructors (and not keeping them default) to ensure the private vector member variable is moved rather than copied, but this is all very confusing to me and I can only seem to find overly simplistic examples of a class with nothing but members of built-in types.

Aucun commentaire:

Enregistrer un commentaire