Homework 6.2b (class
stack
with a pointer data member p
).
The inner parentheses are unnecessary because
==
has higher precedence than -
in C and C++.
The outer parentheses are unnecessary because you don’t need parentheses
around the return value of a function in C and C++.
Put the space
outside
the parentheses, not inside.
bool empty() const { return( (p - a) == 0 ); }
bool empty() const { return p - a == 0; }
bool empty() const { return p == a; }
HW 6.2b.
bool full() const {return p > &a[stack_max_size - 1];}
Get rid of the subtraction.
bool full() const {return p >= &a[stack_max_size];}
Get rid of the
&
and
[]
.
bool full() const {return p >= a + stack_max_size;}
HW 6.2b.
This
size
returns the number of elements in the data member a
,
a number that does not change.
It was supposed to return the number of
int
’s currently stored in the stack,
a number that changes every time we call
push
or
pop
.
size_t size() const { return ( size_t (sizeof a / sizeof a[ 0 ] ) ) ; };
No reason to convert the expression
sizeof a / sizeof a[0]
to the data type
size_t
.
This expression is already of the data type
size_t
.
No need for a semicolon after a function definition.
size_t size() const {return sizeof a / sizeof a[0];}
The above function return the capacity of the stack.
The following function returns the number of
int
’s currently stored in the stack.
size_t size() const {return p - a;}
HW 6.2b.
Do not allow this function to change the value of
src
.
i
should be
size_t
, not
int
.
Write prefix
++
where possible.
The parentheses around the subtraction are unnecessary because
-
has higher precedence than
-
in C and C++.
Get rid of the subtraction:
it’s already been written once and for all in the
size
member function.
// // // stack::stack( stack& src ) { for( int i=0; i<stack_max_size;i++ ) { a[i] = src.a[i]; p = a + (src.p - src.a); } }
I deleted the comments.
stack::stack(const stack& src) { for (size_t i = 0; i < src.size(); ++i) { a[i] = src.a[i]; p = a + src.size(); } }
stack::stack(const stack& src) { for (size_t i = 0; i < src.size(); ++i) { a[i] = src.a[i]; } p = a + src.size(); }
HW 6.2b.
stack::stack(const stack& another) { for (size_t i = 0; i < stack_max_size;++i) { a[i] = another.a[i]; } p = a; //means p = &a[0]; }
stack::stack(const stack& another) { for (size_t i = 0; i < another.size(); ++i) { a[i] = another.a[i]; } p = a + another.size(); }
The above
for
loop has already been written for us.
It’s in the algorithm (i.e., function)
copy
.
//in stack.C #include <algorithm> //for the copy algorithm stack::stack(const stack& another) { p = copy(another.a, another.a + another.size(), a); }
The copy constructor is now short enough to be inline.
//in stack.h #include <algorithm> stack(const stack& another) {p = copy(another.a, another.a + another.size(), a);}
HW 6.2b.
The parens around the subtraction are unnecessary,
because
-
has higher precedence than
<<
in C and C++.
The subtraction is unnecessary because it has already been written
once and for all in the
size
member function.
The bug.
The value of
p
is the
address
of the next free element in the array.
The value of the expression
*p
is the
value
of the next free element in the array.
But this element contains an unpredictable value,
so the
if
behaves unpredictably.
stack::~stack() //destructor { //cout << "destructor for stack\n"; if (*p != 0){ cerr << "Warning: stack still contains " << (p - a) << " value(s).\n"; }
stack::~stack() //destructor { //cout << "destructor for stack\n"; if (p != a){ cerr << "Warning: stack still contains " << p - a << " value(s).\n"; }
stack::~stack() //destructor { //cout << "destructor for stack\n"; if (!empty()){ cerr << "Warning: stack still contains " << size() << " value(s).\n"; }
Now the destructors in Homeworks 6.2a and 6.2b are identical.
HW 6.2a.
size_t size() const { return ( size_t ( n ) ) ; }
The data member
n
is already of data type
size_t
,
so there’s no reason to convert it to size_t
.
size_t size() const {return (n);}
Don’t need parentheses around the return value of a function.
size_t size() const {return n;}
HW 6.2a.
The call to
empty
returns a
bool
which is ignored an thrown away.
stack::~stack() //destructor { //cout << "destructor for stack\n"; empty(); if (n != 0) { cerr << "Warning: stack still contains " << n << " value(s).\n"; } }
stack::~stack() //destructor { //cout << "destructor for stack\n"; if (!empty()) { cerr << "Warning: stack still contains " << size() << " value(s).\n"; } }
The
if
is always false, because of the p = a
Never write an
if
that is always true or always false.
Never give an operand to
p
that is not the address of a dynamically allocated block of memory.
stack::~stack() //destructor { p = a; delete [] p; if (! empty()) { cerr << "Warning: stack still contains " << size() << " values.\n"; } }
stack::~stack() //destructor { if ( !empty()) { cerr << "Warning: stack still contains " << size() << " values.\n"; } }
void stack::push(int i) { if (full()) { //overflow cerr << "Can't push when size " << size() << " == capacity " << stack_max_size << ".\n": exit(EXIT_FAILURE); } p++; }
//in stack.h typedef int value_type;
void stack::push(value_type i) { if (full()) { //overflow cerr << "Can't push when size " << size() << " == capacity " << stack_max_size << ".\n": exit(EXIT_FAILURE); } *p++ = i; //The above statement can be split into //*p = i; //++p; }