unique_ptr在使用基类时的析构函数序列

huangapple go评论77阅读模式
英文:

sequence of destructors when using unique_ptr to base class

问题

我正在尝试使用std::unique_ptr和类继承(即多态性)。我正在运行以下代码:

#include <iostream>
#include <memory>

class polygon {
public:
    int side;
    polygon(int i) : side(i) { std::cout << "polygon created" << std::endl; }
    virtual int perimeter() = 0;
    ~polygon() { std::cout << "polygon destroyed" << std::endl; }
};
class triangle : public polygon {
public:
    triangle(int i) : polygon::polygon{i} { std::cout << "triangle created" << std::endl; }
    int perimeter() { return side * 3; }
    ~triangle() { std::cout << "triangle destroyed" << std::endl; }
};
class square : public polygon {
public:
    square(int i) : polygon::polygon{i} { std::cout << "square created" << std::endl; }
    int perimeter() { return side * 4; }
    ~square() { std::cout << "square destroyed" << std::endl; }
};

int main() {
    std::unique_ptr<polygon> pp = std::make_unique<square>(5); // (1)
    std::cout << pp->perimeter() << std::endl;

    pp = std::make_unique<triangle>(4); // (2)
    std::cout << pp->perimeter() << std::endl;

    return 0;
}

我可以看到析构函数按与构造函数相反的顺序调用,这也适用于基类派生类构造函数和析构函数的顺序。

但是,只有polygon的析构函数被调用,也就是在分配(我猜是因为第一个std::make_unique<square>被销毁,或者当返回0时)。这是否意味着在销毁基类std::unique_ptr时,分配给(1)和(2)中的派生类对象的内存会泄漏?

英文:

I am experimenting with std::unique_ptr and class inheritance (i.e. polymorphism somehow). The code I am running is the following:

#include&lt;iostream&gt;
#include&lt;memory&gt;

class polygon {
    public:
    int side;
    polygon(int i): side(i) {std::cout&lt;&lt;&quot;polygon created&quot;&lt;&lt;std::endl;}
    virtual int perimeter() = 0;
    ~polygon() {std::cout&lt;&lt;&quot;polygon destroyed&quot;&lt;&lt;std::endl;}
};
class triangle : public polygon {
    public:
    triangle(int i): polygon::polygon{i} {std::cout&lt;&lt;&quot;triangle created&quot;&lt;&lt;std::endl;}
    int perimeter() { return side*3; }
    ~triangle() {std::cout&lt;&lt;&quot;triangle destroyed&quot;&lt;&lt;std::endl;}
};
class square : public polygon {
    public:
    square(int i): polygon::polygon{i} {std::cout&lt;&lt;&quot;square created&quot;&lt;&lt;std::endl;}
    int perimeter() { return side*4; }
    ~square() {std::cout&lt;&lt;&quot;square destroyed&quot;&lt;&lt;std::endl;}
};

int main() {
    std::unique_ptr&lt;polygon&gt; pp = std::make_unique&lt;square&gt;(5); // (1)
    std::cout &lt;&lt; pp-&gt;perimeter() &lt;&lt; std::endl;

    pp = std::make_unique&lt;triangle&gt;(4); // (2)
    std::cout &lt;&lt; pp-&gt;perimeter() &lt;&lt; std::endl;

    return 0;
}

I can see that destructors are invoked in reverse order with respect to constructors, and that applies also to base class-derived class sequences of constructors and destructors.

However, only the polygon destructors are invoked, i.e. when assigning (I guess because the first std::make_unique&lt;square&gt; is destroyed, or when returning 0. Does that mean that when destroying a base class std::unique_ptr, the memory allocated to the derived class objects in (1) and (2) is leaked?

答案1

得分: 5

是的,在C++中,如果你通过指向基类的指针删除对象(就像你所做的那样),你必须明确将基类的析构函数标记为virtual。所以将polygon的析构函数更改为:

virtual ~polygon() {std::cout << "polygon destroyed" << std::endl;}

附注:将你的perimeter函数声明为const

英文:

Yes, in C++ you have to explicitly mark your destructor virtual in the base class, if you delete through a pointer to the base class (as you do). So change the destructor of polygon to:

virtual ~polygon() {std::cout&lt;&lt;&quot;polygon destroyed&quot;&lt;&lt;std::endl;}

PS: Make your perimeter function const.

huangapple
  • 本文由 发表于 2023年2月27日 00:06:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/75573247.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定