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

Date与Employee类构造/析构函数调用次数差异及执行序列问询

Hey,作为C++新手遇到这种构造析构次数不一致的问题太正常了,咱们一点点拆解清楚:

先看你的代码

Date.h

#include<iostream>
#include<cstdlib>
#include<cstring>
using namespace std;
class Date{
private:
    int day;
    int month;
    int year;
public:
    Date(int d = 1, int m = 1, int y = 1900): day(d), month(m), year(y) {
        cout << "date constructor is called" << endl;
    }
    void print() const {
        cout << day << ":" << month << ":" << year << endl;
    }
    ~Date(){
        cout << "date destructor is called" << endl;
    }
};

Employee.h

#include"Date.h"
class Employee{
private:
    char *fname;
    char *lname;
    Date dob; // has-a关系
    Date hiredate; // has-a关系
public:
    Employee(char *f, char *l, Date bd, Date hd){
        cout << "employee constructor is called" << endl;
        int lengthf;
        lengthf = strlen(f);
        fname = new char[lengthf+1];
        strcpy(fname, f);
        int lengthl;
        lengthl = strlen(l);
        lname = new char[lengthl +1];
        strcpy(lname, l);
    }
    ~Employee(){
        delete [] fname;
        delete [] lname;
        cout << "employee destructor is called" << endl;
    }
};

主函数

#include"Employee.h"
int main(){
    Date db(07, 11, 1991);
    Date dh;
    dh.print();
    Employee e("Dan", "Lee", db, dh);
    db.print();
    system("pause");
    return 0;
}

问题1:为啥Date构造4次、析构6次?

核心原因就是按值传递参数会生成临时拷贝对象,但这里有个关键细节:你的Date类没有显式定义拷贝构造函数,编译器会自动生成一个默认拷贝构造——但这个默认拷贝构造不会执行你写的那个带cout输出的构造函数,所以这两次拷贝的构造不会被你统计到。

而临时拷贝对象销毁时,会调用你显式写的析构函数,所以就多了2次析构,最终构造4次、析构6次。


问题2:完整的构造&析构调用序列

咱们按代码执行的顺序一步步捋,把每个节点的调用都列出来:

构造函数调用(带输出的4次):

  1. 执行Date db(07, 11, 1991); → 调用带参构造,输出date constructor is called(第1次)
  2. 执行Date dh; → 调用默认构造,输出date constructor is called(第2次)
  3. 创建Employee e时,C++会先初始化类的成员变量(在构造函数体执行前):
    • 初始化dob → 调用Date默认构造,输出date constructor is called(第3次)
    • 初始化hiredate → 调用Date默认构造,输出date constructor is called(第4次)
  4. 进入Employee构造函数体,输出employee constructor is called

    注意:这里传递的参数bd和hd是按值传递,编译器用默认拷贝构造生成了两个临时Date对象,但因为默认拷贝构造没有输出,所以你看不到这两次构造的打印。

析构函数调用(共6次,顺序是栈式的“后进先出”):

  1. Employee构造函数执行完毕后,传递参数时生成的两个临时Date对象(bd和hd的拷贝)被销毁 → 调用2次Date析构,输出date destructor is called(第1、2次)
  2. system("pause")执行完成后,main函数开始销毁局部变量:
    • 先销毁Employee e:
      • 执行Employee析构函数体,输出employee destructor is called
      • 销毁Employee的成员变量:先销毁hiredate → 调用Date析构(第3次),再销毁dob → 调用Date析构(第4次)
    • 接着销毁dh → 调用Date析构(第5次)
    • 最后销毁db → 调用Date析构(第6次)

问题3:按值传递vs按引用传递的差异

按值传递时析构次数增多的原因:

按值传递参数时,C++必须创建一个参数的独立拷贝——这个拷贝是全新的对象,在函数/构造函数执行完成后,这个临时对象就会被立即销毁,所以会多一次析构调用。你的代码里有两个Date类型的按值参数,就多了2次析构,导致析构次数比构造多。

按引用传递时次数一致的原理:

如果把Employee构造函数改成按引用传递(建议加const避免意外修改):

Employee(char *f, char *l, const Date& bd, const Date& hd)

这时候,bd和hd只是原对象(db和dh)的“别名”,不会创建任何新的Date对象。所以构造次数还是4次(db、dh、dob、hiredate),析构次数也是这4个对象的析构,Date的构造和析构次数就完全一致了。


内容的提问来源于stack exchange,提问作者Rizwan Muzaffar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 16:02:40