You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何下述C++代码中析构函数会被调用两次?

析构函数调用次数解析:AaBbdDdD输出拆解

先贴出问题中的代码:

#include <iostream>

struct Person {
    Person() { std::cout << "A"; }              // Constructor
    Person(const Person& other) { std::cout << "B"; }  // Copy constructor
    ~Person() { std::cout << "D"; }             // Destructor
};

struct Student : public Person { // Correct inheritance
    Student() { std::cout << "a"; }              // Constructor
    Student(const Student& other) : Person(other) { std::cout << "b"; }  // Copy constructor
    ~Student() { std::cout << "d"; }             // Destructor
};

int main() {
    Student* s1 = new Student;   // Create Student object on heap
    Student s2 = *s1;             // Call copy constructor
    *s1 = s2;                    // Use copy assignment operator
    delete s1;                   // Delete the dynamically allocated memory
    return 0;
}

我们逐行拆解代码执行时的输出逻辑:

  • Student* s1 = new Student;
    新建堆上的Student对象时,会先调用基类Person的构造函数(输出"A"),再调用子类Student的构造函数(输出"a"),这部分对应输出开头的Aa。

  • Student s2 = *s1;
    通过拷贝构造创建栈上的s2对象时,先触发基类Person的拷贝构造(输出"B"),再触发子类Student的拷贝构造(输出"b"),这部分对应输出的Bb。

  • *s1 = s2;
    这里调用的是编译器默认生成的拷贝赋值运算符,默认赋值只会拷贝成员变量,不会调用构造或析构函数,因此无输出。

  • delete s1;
    销毁堆上的Student对象时,先调用子类Student的析构函数(输出"d"),再调用基类Person的析构函数(输出"D"),这部分对应输出的dD。

  • main函数结束,局部变量s2销毁
    栈上的s2对象在main函数退出时自动销毁,同样先调用子类Student的析构函数(输出"d"),再调用基类Person的析构函数(输出"D"),这部分对应输出的dD。

把所有输出拼接起来就是AaBbdDdD。你觉得析构函数只被调用两次是因为忽略了每个对象销毁时都会触发子类+基类两次析构的规则——这里共有两个独立的Student对象(堆上一个、栈上一个),所以总共触发4次析构调用(2次Student析构、2次Person析构)。

内容的提问来源于stack exchange,提问作者3nondatur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 22:47:45