Exercises in this lecture   Go to the notes, in which this exercise belongs -- Keyboard shortcut: 'u'   Alphabetic index   Course home   

Exercise solution:
Point destruction - now with a problematic point copy constructor


The two problems are

  1. When r is copied to s both r and s refer to the same point representation (because the pointer is copied in the Point copy constructor.
  2. When s goes out of scope, the Point destructor is called. Hereby delete is called on the memory, which already has been deleted because also r goes out of scope.

Here is an improved version of the implementation of class Point. Notice the improved copy constructor. In this version, it copies the point representation.

#include <cmath>
#include <iostream>
#include "point.h"


Point::Point(){
  point_representation = new double[2];
  point_representation[0] = 0.0;
  point_representation[1] = 0.0;
}

Point::Point(double x_coord, double y_coord){
  point_representation = new double[2];
  point_representation[0] = x_coord;
  point_representation[1] = y_coord;
}

Point::Point(Point& p){   // Better copy constructor
  point_representation = new double[2];
  point_representation[0] = p.getx();
  point_representation[1] = p.gety();
}

Point::~Point(){
  std::cout << "Deleting point" << "(" << getx() << "," << gety() << ")" << std::endl;
  delete[] point_representation;
}


double Point::getx () const{
  return point_representation[0];
}

double Point::gety () const{
  return point_representation[1];
}

void Point::move(double dx, double dy){
  point_representation[0] += dx;
  point_representation[1] += dy;
}

std::ostream& operator<<(std::ostream& s, const Point& p){
  return s << "(" << p.getx() << "," << p.gety() << ")" ;
}

The client program is here (only comments have been changed):

#include <iostream>
#include "point.h"

using namespace std;

int f(){

  Point p, q,                         
        r(11.0, 12.0);

  cout << "Point p: "      << p << endl;         // (0,0)
  cout << "Point q: "      << q << endl;         // (0,0)
  cout << "Point r: "      << r << endl;         // (11,12)

  Point s(r);
  cout << "Point s: "      << s << endl << endl; // (11,12)

  r.move(1.0, 2.0);

  cout << "Point s: "      << s << endl;         // (11,12)   
  cout << "Point r: "      << r << endl << endl; // (12,14)

  // Now f returns, and the program runs as expected. The reason is that
  // s now refers to a copy of the representation of r. Thus, both
  // r and s can be safely deleted when they go out of scope (when f returns to main).
}

int main(){
  f();
}