Вот код
#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)
Я ожидаю, что каждая точка будет уничтожена дважды, но вместо этого они уничтожаются трижды. Зачем?
Так как
Square(Point p1, Point p2)
принимает аргументы, передаваемые по значению, которое создает копию параметров, которые вы передаете ему. Так что у тебя есть
Square
конструкторSquare
вы создаете3 экземпляра.
вы копируете их в конструктор
пытаться 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)
Этот конструктор
Square(Point p1, Point p2) : upperleft(p1), lowerright(p2) {}
принимает объекты типа Point по значению. Таким образом, эти временные объекты, созданные в качестве параметров конструктора, также удаляются.
Вы можете определить конструктор следующим образом
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)
означает, что компилятор сначала создал второй аргумент Point (3, 4), а затем первый аргумент Point (1, 2). Они удаляются в обратном порядке.
Эти две линии
Point destroyed: (3, 4)
Point destroyed: (1, 2)
означает, что сначала был создан элемент данных upperleft, потому что он был объявлен до того, как был создан нижний правый, а затем нижний правый. Снова они удаляются в обратном порядке.
И наконец эти две строки
Point destroyed: (3, 4)
Point destroyed: (1, 2)
означает, что сначала точка (1, 2) была создана, потому что она определена до создания точки (3, 4) в главной, а затем точка (3, 4). Они удаляются в обратном порядке.
Уничтожить дважды, используя ссылки:
#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;
}