2014-01-30 2 views
1

Вот кодПочему эти точки уничтожены три раза?

#include <iostream> 
#include <stdio.h> 
using namespace std; 

class Point { 
    private: 
     int x; 
     int y; 
    public: 
     Point(int x, int y) : x(x), y(y) {} 
     ~Point() { 
      printf("Point destroyed: (%d, %d)\n", x, y); 
     } 
}; 

class Square { 
    private: 
     Point upperleft; 
     Point lowerright; 
    public: 
     Square(int x1, int y1, int x2, int y2) : upperleft(x1, y1), lowerright(x2, y2) {} 
     Square(Point p1, Point p2) : upperleft(p1), lowerright(p2) {} 
     ~Square() { 
      printf("Square destroyed.\n"); 
     } 
}; 

int main(int argc, char const* argv[]) 
{ 
    Point p1(1, 2); 
    Point p2(3, 4); 
    Square s1(p1, p2); 
    return 0; 
} 

После компиляции (g++ x.cpp) и бежать, я получил следующие результаты:

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) 

я ожидаю каждый пункт, чтобы быть уничтожены в два раза, но они уничтожены три раза вместо , Зачем?

+0

Какой компилятор и какие варианты? –

+0

p1 и p2 будут уничтожены, как и копии, сделанные при передаче их конструктору «Квадрат», а затем вторая пара копий, созданных при построении ваших данных из этих копий. – Simple

+0

@JohnZwinck Plz см. В редакции. – qed

ответ

4

Поскольку

Square(Point p1, Point p2) 

принимает аргументы, передаваемые по значению, которое создает копию параметров, которые Вы передаете к нему.Таким образом, у вас есть

  1. Исходные параметры
  2. Копии, переданные Square конструктор
  3. Переменные-члены экземпляра Square создать

3 экземпляров.

+0

Итак, в общей сложности есть две копии, почему они были уничтожены три раза? – qed

+0

@qed Когда вы передаете параметры ** по значению ** в функцию, временные копии сделаны из исходных аргументов. – mathematician1975

+2

@qed Три копии: оригинал в функции 'main', копия, переданная по значению конструктору, и переменная-член' Square'. –

2

скопировать их в конструктор

попробовать Square(const Point& p1,const Point& p2) : upperleft(p1), lowerright(p2) {}

результаты в

Square destroyed. 
Point destroyed: (3, 4) 
Point destroyed: (1, 2) 
Point destroyed: (3, 4) 
Point destroyed: (1, 2) 
2

Этот конструктор

Square(Point p1, Point p2) : upperleft(p1), lowerright(p2) {} 

принимает объекты типа точки по значению. Таким образом, эти временные объекты, созданные как параметры конструктора, также удаляются.

Вы можете определить конструктору следующим образом

Square(const Point &p1, const Point &p2) : upperleft(p1), lowerright(p2) {} 

, чтобы избежать создания временных объектов во время ее вызова.

Интересно увидеть порядок, в котором деструкторов называются

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) 

Эти две линии

Point destroyed: (1, 2) 
Point destroyed: (3, 4) 

означает, что компилятор сначала создал второй аргумент точки (3, 4) и то первый аргумент Point (1, 2). Они удаляются в обратном порядке.

Эти две линии

Point destroyed: (3, 4) 
Point destroyed: (1, 2) 

означает, что в первом элементе данных левого верхнего была создана, поскольку она объявлена ​​до lowerright, а затем lowerright был создан. Опять же они удаляются в обратном порядке.

И наконец эти две линии

Point destroyed: (3, 4) 
Point destroyed: (1, 2) 

означает, что в первой точке (1, 2) была создана, поскольку она определяется до точки (3, 4) в основной и затем Point (3, 4) был создан. Они удаляются в обратном порядке.

0

уничтожить дважды, используя ссылки:

#include <iostream> 
#include <stdio.h> 
using namespace std; 

class Point { 
    private: 
     int x; 
     int y; 
    public: 
     Point(int x, int y) : x(x), y(y) {} 
     ~Point() { 
      printf("Point destroyed: (%d, %d)\n", x, y); 
     } 
}; 

class Square { 
    private: 
     Point upperleft; 
     Point lowerright; 
    public: 
     Square(int x1, int y1, int x2, int y2) : upperleft(x1, y1), lowerright(x2, y2) {} 
     Square(Point& p1, Point& p2) : upperleft(p1), lowerright(p2) {} 
     ~Square() { 
      printf("Square destroyed.\n"); 
     } 
}; 

int main(int argc, char const* argv[]) 
{ 
    Point p1(1, 2); 
    Point p2(3, 4); 
    Square s1(p1, p2); 
    return 0; 
} 

уничтожить один раз, используя указатели:

#include <iostream> 
#include <stdio.h> 
using namespace std; 

class Point { 
    private: 
     int x; 
     int y; 
    public: 
     Point(int x, int y) : x(x), y(y) {} 
     ~Point() { 
      printf("Point destroyed: (%d, %d)\n", x, y); 
     } 
}; 

class Square { 
    private: 
     Point* upperleft; 
     Point* lowerright; 
    public: 
     Square(int x1, int y1, int x2, int y2) { 
      Point* ul = new Point(x1, y1); 
      Point* lr = new Point(x2, y2); 
      upperleft = ul; 
      lowerright = lr; 
     } 
     Square(Point* p1, Point* p2) : upperleft(p1), lowerright(p2) {} 
     ~Square() { 
      printf("Square destroyed.\n"); 
     } 
}; 

int main(int argc, char const* argv[]) 
{ 
    Point p1(1, 2); 
    Point p2(3, 4); 
    Square s1(&p1, &p2); 
    return 0; 
} 
Смежные вопросы