user385261
user385261

Reputation: 4169

Is the book wrong?

template <typename T>
  class Table {
    public:
      Table();
      Table(int m, int n);
      Table(int m, int n, const T& value);
      Table(const Table<T>& rhs);
      ~Table();
      Table<T>& operator=(const Table& rhs);
      T& operator()(int i, int j);
      int numRows()const;
      int numCols()const;
      void resize(int m, int n);
      void resize(int m, int n, const T& value);
    private:
      // Make private because this method should only be used
      // internally by the class.
      void destroy();
    private:
      int mNumRows;
      int mNumCols;
      T** mDataMatrix;
  };

template <typename T>
  void Table<T>::destroy() {
    // Does the matrix exist?
    if (mDataMatrix) {
      for (int i = 0; i < _m; ++i) {
        // Does the ith row exist?
        if (mDataMatrix[i]) {
          // Yes, delete it.
          delete[]mDataMatrix[i];
          mDataMatrix[i] = 0;
        }
      }

      // Delete the row-array.
      delete[] mDataMatrix;
      mDataMatrix = 0;
    }

    mNumRows = 0;
    mNumCols = 0;
  }

This is a code sample I got from a book. It demonstrates how to destroy or free a 2x2 matrix where mDataMatrix is the pointer to array of pointers.

What I don't understand is this part:

for(int i = 0; i < _m; ++i) {
  // Does the ith row exist?
  if (mDataMatrix[i]) {
    //.….

  }
}

I don't know why the book uses _m for max number of row-ptr. It wasn't even a variable define in class; the variable for max row is mNumRows. Maybe it is some compiler pre-defined variable? Another thing I am quite confuse is why is it ++i? pre-operator, why not i++? Will it make different if I change it into i++?

Upvotes: 2

Views: 403

Answers (6)

MarkD
MarkD

Reputation: 4944

Without seeing the entire class code, it is hard to tell for your first question, but if it hasn't been defined as part of the class, my guess would be that it is a typo.

as for your second question, ++i vs. i++, the prefix increment operator (++i) returns the object you are incrementing, whereas the postfix increment operator returns a copy of the object, in the objects original state. i.e.-

int i=1;
std::cout << i++ << std::endl;  // output:  1
std::cout << i << std::endl     // output:  2
std::cout << ++i << std::endl   // output:  3

as for will the code change with the postfix- no, it works the same in loops, and makes basically no difference in loops for integer types. For user defined types, however, it may be more efficient to use the prefix increment, and is the style many c++ programmers use by default.

Upvotes: 3

Matthieu M.
Matthieu M.

Reputation: 299730

The real mess with this book is the way it illustrates a 2x2 matrix. The problem is here that for 4 elements you have 3 blocks of memory allocated, and not only does it slows down the program but it is certainly much more tricky to handle.

The usual technic is much simpler:

T* mData = new T[2*2];

And then you access it like so:

T& operator()(size_t r, size_t c) { return mData[r * mNbRows + c]; }

This is a bit more work (you have to multiply by the number of rows if you are row major), but then the destroy is incredibly easy:

template <class T>
void Table<T>::destroy()
{
  delete[] mData;
  mData = 0;
  mNbRows = 0;
  mNbColumns = 0;
}

Also note that here there is no need for a if: it's fine to call delete on a null pointer, it just doesn't do anything.

Finally, I have no idea why your book is using int for coordinates, do negative coordinates have any meaning in the context of this Table class ? If not, you're better off using an unsigned integral type (like size_t) and throwing the book away.

Upvotes: 0

TheJuice
TheJuice

Reputation: 4484

As others have said, the prefix operator is preferred for performance reasons when dealing with user-defined types. The reason it has no impact on the for loop is because the test involving the value of the variable (i.e. i < _m) is performed before the operation that modifies the variable is performed.

Upvotes: 0

sth
sth

Reputation: 229563

If the _mvariable isn't defined anywhere this is an error. From that context it looks like it should contain the number of rows that are allocated with new somewhere (probably in the constructor, or there might be methods like addRow). If that number is always mNumRows, than this would be appropriate for the loop in the destructor.

If you use ++i or i++ in that for loop doesn't make any difference. Both variants increment the integer, and the return value of the expression (that would be different) isn't used anywhere.

Upvotes: 2

fredoverflow
fredoverflow

Reputation: 263058

Another thing I am quite confuse is why is it ++i? pre-operator, why not i++? Will it make different if I change it into i++?

Because ++i is more natural and easier to understand: increment i and then yield the variable i as a result. i++ on the other hand means copy the current value of i somewhere (let's call it temp), increment i, and then yield the value temp as a result.

Also, for user-defined types, i++ is potentially slower than ++i.

Note that ++i as a loop increment does not imply the increment happens before entering the loop body or something. (This seems to be a common misconception among beginners.) If you're not using ++i or i++ as part of a larger expression, the semantics are exactly the same, because prefix and postfix increment only differ in their result (incremented variable vs. old value), not in their side effect (incrementing the variable).

Upvotes: 5

Dave McClelland
Dave McClelland

Reputation: 3413

I can't speak to the first part of the question, but I can explain the pre- versus post- increment dilemma.

Prefix versions increment and decrement are slightly more efficient and are generally preferred. In the end, though, the extra overhead caused by using i++ over ++i is negligible unless the loop is being executed many, many times.

Upvotes: 0

Related Questions