This constructor
Square(Point p1, Point p2) : upperleft(p1), lowerright(p2) {}
accepts objects of type Point by value. So these temporary objects that created as parameters of the constructor are also deleted.
You could define the constructor the following way
Square( const Point &p1, const Point &p2) : upperleft(p1), lowerright(p2) {}
to escape creating temporary objects during its call.
It is interesting to see the order in which destructors are called
Point destroyed: (1, 2)
Point destroyed: (3, 4)
Square destroyed.
Point destroyed: (3, 4)
Point destroyed: (1, 2)
Point destroyed: (3, 4)
Point destroyed: (1, 2)
These two lines
Point destroyed: (1, 2)
Point destroyed: (3, 4)
mean that the compiler at first created the second argument Point(3, 4) and then the first argument Point( 1, 2 ). They are deleted in the reverse order.
These two lines
Point destroyed: (3, 4)
Point destroyed: (1, 2)
mean that at first data member upperleft was created because it declared before lowerright and then lowerright was created. Again they are deleted in the reverse order.
And at last these two lines
Point destroyed: (3, 4)
Point destroyed: (1, 2)
mean that at first Point( 1, 2 ) was created because it is defined before Point( 3, 4 ) in main and then Point( 3, 4 ) was created. They are deleted in the reverse order.