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++?
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).
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.
If the _m
variable 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.
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.
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.
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.
精彩评论