[comp.lang.c++] Following code bombs

rsc@erc3ba.UUCP (Rich Chomiczewski, AT&T - ERC, Princeton NJ) (03/05/88)

The following program blows the stack:

// --------------------- Cut Here --------------------
#include <stream.h>

class Point {
	int xc, yc;	// x-y coordinates
public:
	Point(int x =0, int y =0)	{ xc = x; yc = y; }
	int x()				{ return xc; }
	int y()				{ return yc; }
	Point operator+(Point p)	{ return Point(xc+p.xc, yc+p.yc); }
};
ostream& operator<<(ostream& oo, Point p)
{
	return oo << "(" << p.x() << "," << p.y() << ")";
}

class Position {
	Point off;	// offset is relative to (possibly null) ``to''.
	Position *to;
public:
	Position()			{ off = Point(0,0); to = 0; }
	Position(Point p)		{ off = p; to = 0; }
	Position(Point p, Position pos)	{ off = p; to = &pos; }
	Point position()		{ return (to) ? off+to->position() : off; }
};
ostream& operator<<(ostream& oo, Position p)
{
	return oo << p.position();
}

main()
{
	Position a = Position(Point(1,1));
	Position b = Position(Point(5,5), a);
	Position c = Position(Point(10,10), b);

	cerr << a;
	cerr << b;
	cerr << c;
}
// --------------------- Cut Here --------------------

One of the more difficult aspects of programming in c++ for me is
the correct handling of assignment and initialization of classes (which
I suspect is the root of the problem here).

So, given the above declaration of class Position what is the "correct"
definition of the member functions ``Position::Position(Position&)'' and 
``Position::operator=(Position&)''?

Thanks,
Rich Chomiczewski (ihnp4!erc3ba!rsc)

fuchs@gmdka.UUCP (Harald Fuchs) (03/08/88)

in article <400@erc3ba.UUCP>, rsc@erc3ba.UUCP (Rich Chomiczewski, AT&T - ERC, Princeton NJ) says:
> The following program blows the stack:
> ...
> class Position {
> 	Point off;	// offset is relative to (possibly null) ``to''.
> 	Position *to;
> public:
> 	Position(Point p)		{ off = p; to = 0; }
> 	Position(Point p, Position pos)	{ off = p; to = &pos; }
> 	Point position()		{ return (to) ? off+to->position() : off; }
> };

> main()
> {
> 	Position a = Position(Point(1,1));
> 	Position b = Position(Point(5,5), a);
> 	Position c = Position(Point(10,10), b);
> }

The bug in this program is
	Position(Point p, Position pos)	{ off = p; to = &pos; }
where you take the address of an object on the stack because pos is passed
by value. Use reference passing (Position& pos) and the problem disappears.

When you declare
 	Position a = Position(Point(1,1));
the following functions are called:
  Position::Position (Point);            // To make a temporary Position value
  Position::Position (Position&);        // Initialisation of a by temp
					 // See The Book p. 180
  Position::~Position ();                // To get rid of temp
Since you didn't declare Position::Position (Position&), Cfront picks the
default, namely bitwise copy. That happens to be ok in this context.

                               Harald Fuchs

UUCP:  ...!uunet!mcvax!unido!gmdka!fuchs
X.400: fuchs@karlsruhe.gmd.dbp.de