为什么这些点被摧毁了三次?

时间:2014-01-30 14:18:34

标签: c++ destroy

这是代码

#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)

我希望每个Point都被销毁两次,但它们会被销毁三次。为什么呢?

4 个答案:

答案 0 :(得分:4)

由于

Square(Point p1, Point p2)

接受按值传递的参数,该参数创建传递给它的参数的副本。你有

  1. 原始参数
  2. 传递给Square构造函数
  3. 的副本
  4. 您创建的Square实例的成员变量
  5. 3个实例。

答案 1 :(得分: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 :(得分: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)

表示首先创建数据成员左上角,因为它在lowerright之前声明,然后创建了lowerright。同样,它们会以相反的顺序删除。

最后这两行

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

表示首先创建Point(1,2),因为它是在main(而Point)中的Point(3,4)之前定义的,然后创建了Point(3,4)。它们以相反的顺序删除。

答案 3 :(得分: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;
}