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