news 2026/5/1 10:03:24

C++构造函数与析构函数:对象生命周期的守护者

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++构造函数与析构函数:对象生命周期的守护者

C++构造函数与析构函数:对象生命周期的守护者

引言:为什么需要特殊的初始化函数?

在C++中,我们希望使用类对象就像使用基本类型一样方便。比如,我们可以这样初始化一个整数或结构体:

intyear=2001;structthing{char*pn;intm;};thing amabob={"wodget",-23};

但为什么不能这样初始化Stock对象呢?

Stock hot={"Sukie Autos, Inc.",200,50.25};// 错误!

原因在于数据封装:类成员通常是私有的,不能直接从外部访问。我们需要一种特殊的方法来初始化对象,这就是构造函数的用武之地。

构造函数:对象的"出生证明"

什么是构造函数?

构造函数是一种特殊的成员函数,在创建对象时自动调用。它的名称与类名相同,没有返回类型(连void都不是)。

声明和定义构造函数

让我们为Stock类添加构造函数:

// 构造函数原型Stock(conststd::string&co,longn=0,doublepr=0.0);// 构造函数定义Stock::Stock(conststd::string&co,longn,doublepr){company=co;if(n<0){std::cerr<<"Number of shares can't be negative; "<<company<<" shares set to 0.\n";shares=0;}else{shares=n;}share_val=pr;set_tot();// 计算总价值}

使用构造函数的两种方式

显式调用:

Stock food=Stock("World Cabbage",250,1.25);

隐式调用:

Stockgarment("Furry Mason",50,2.5);

与new一起使用:

Stock*pstock=newStock("Electroshock Games",18,19.0);

默认构造函数:对象的"默认设置"

默认构造函数是在未提供初始值时使用的构造函数。例如:

Stock fluffy_the_cat;// 使用默认构造函数

重要原则:

  • 如果没有定义任何构造函数,编译器会自动生成一个不做任何事的默认构造函数
  • 但如果定义了任何构造函数,就必须手动提供默认构造函数

定义默认构造函数的两种方法:

  1. 为已有构造函数的参数提供默认值:
Stock(conststd::string&co="Error",intn=0,doublepr=0.0);
  1. 重载一个无参数的构造函数:
Stock();// 默认构造函数

推荐做法:始终提供对类成员做隐式初始化的默认构造函数。

析构函数:对象的"临终关怀"

当对象生命周期结束时,析构函数自动被调用,用于清理资源。

定义析构函数

析构函数名为~类名,没有参数和返回类型:

// 析构函数原型~Stock();// 析构函数定义Stock::~Stock(){std::cout<<"Bye, "<<company<<"!\n";}

何时调用析构函数?

  • 静态对象:程序结束时
  • 自动对象:离开其作用域时
  • 动态对象:使用delete释放内存时
  • 临时对象:结束使用时

完整示例:改进的Stock类

头文件 (stock10.h)

#ifndefSTOCK10_H_#defineSTOCK10_H_#include<string>classStock{private:std::string company;longshares;doubleshare_val;doubletotal_val;voidset_tot(){total_val=shares*share_val;}public:Stock();// 默认构造函数Stock(conststd::string&co,longn=0,doublepr=0.0);~Stock();// 析构函数voidbuy(longnum,doubleprice);voidsell(longnum,doubleprice);voidupdate(doubleprice);voidshow()const;// const成员函数};#endif

实现文件 (stock10.cpp)

#include<iostream>#include"stock10.h"// 默认构造函数Stock::Stock(){std::cout<<"Default constructor called\n";company="no name";shares=0;share_val=0.0;total_val=0.0;}// 带参数的构造函数Stock::Stock(conststd::string&co,longn,doublepr){std::cout<<"Constructor using "<<co<<" called\n";company=co;if(n<0){std::cout<<"Number of shares can't be negative; "<<company<<" shares set to 0.\n";shares=0;}else{shares=n;}share_val=pr;set_tot();}// 析构函数Stock::~Stock(){std::cout<<"Bye, "<<company<<"!\n";}// 其他成员函数实现...

使用示例 (usestock2.cpp)

#include<iostream>#include"stock10.h"intmain(){{usingstd::cout;cout<<"Using constructors to create new objects\n";Stockstock1("NanoSmart",12,20.0);// 隐式调用stock1.show();Stock stock2=Stock("Boffo Objects",2,2.0);// 显式调用stock2.show();cout<<"Assigning stock1 to stock2:\n";stock2=stock1;cout<<"Using a constructor to reset an object\n";stock1=Stock("Nifty Foods",10,50.0);// 创建临时对象并赋值stock1.show();cout<<"Done\n";}// 离开作用域,析构函数被调用return0;}

C++11新特性:列表初始化

C++11允许使用列表初始化语法初始化对象:

// 匹配带参数的构造函数Stock hot_tip={"Derivatives Plus Plus",100,45.0};Stock jock{"Sport Age Storage, Inc"};// 使用默认参数Stock temp{};// 默认构造函数

const成员函数:承诺不修改对象

对于const对象,只能调用不会修改对象状态的成员函数:

constStock land=Stock("Kludgehorn Properties");land.show();// 需要show()是const成员函数

如何声明const成员函数?

// 声明voidshow()const;// 定义voidStock::show()const{// 不能修改任何成员变量std::cout<<"Company: "<<company<<"\n";}

最佳实践:只要成员函数不修改对象,就应将其声明为const。

构造函数和析构函数总结表

特性构造函数析构函数
名称与类名相同~类名
返回类型
参数可以有(可重载)
调用时机创建对象时销毁对象时
主要用途初始化对象清理资源
默认版本无自定义构造函数时自动生成始终自动生成(可自定义)

构造函数使用技巧

单参数构造函数的隐式转换:

Bozo dribble=44;// 隐式调用Bozo(44)

避免隐式转换(C++11):

explicitBozo(intn);// 禁止隐式转换

关键要点

  1. 构造函数是对象的"出生证明",负责初始化工作
  2. 析构函数是对象的"临终关怀",负责清理工作
  3. 如果定义了任何构造函数,必须手动提供默认构造函数
  4. 使用const成员函数保证不修改对象状态
  5. C++11的列表初始化让对象创建更简洁
  6. 构造函数可以使用默认参数减少重载数量

记住:良好的类设计应该让对象"生得正确,死得干净"。构造函数和析构函数正是实现这一目标的关键工具!


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 8:38:10

【完整源码+数据集+部署教程】工图机械零件特征图像分割系统源码&数据集分享 [yolov8-seg-LAWDS&yolov8-seg-RevCol等50+全套改进创新点发刊_一键训练教程_Web前端

背景意义 随着工业自动化和智能制造的迅速发展&#xff0c;机械零件的检测与识别在生产过程中变得愈发重要。传统的人工检测方法不仅效率低下&#xff0c;而且容易受到人为因素的影响&#xff0c;导致误判和漏判。因此&#xff0c;基于计算机视觉的自动化检测技术逐渐成为研究的…

作者头像 李华
网站建设 2026/5/1 7:36:06

【完整源码+数据集+部署教程】垃圾分类分割系统源码&数据集分享 [yolov8-seg-GFPN&yolov8-seg-timm等50+全套改进创新点发刊_一键训练教程_Web前端展示]

背景意义 随着城市化进程的加快和人口的不断增长&#xff0c;垃圾产生量急剧增加&#xff0c;垃圾分类和处理问题日益凸显。垃圾的无序堆放不仅占用大量土地资源&#xff0c;还对环境造成了严重污染&#xff0c;影响了人们的生活质量。因此&#xff0c;如何有效地进行垃圾分类&…

作者头像 李华
网站建设 2026/5/1 7:34:50

超越Git:迈向数据驱动的机器学习模型版本管理

好的&#xff0c;遵照您的要求&#xff0c;基于随机种子 1770681600067 所启发的思考方向&#xff0c;我将为您撰写一篇关于“模型版本管理”的深度技术文章。本文将从数据驱动的视角切入&#xff0c;探讨超越传统代码版本控制的模型管理范式。 超越Git&#xff1a;迈向数据驱动…

作者头像 李华
网站建设 2026/5/1 8:54:16

2000-2025年县域5A级旅游景区DID

数据简介 针对区县是否有 5A 级景区可展开的研究&#xff0c;可以围绕 5A 景区与区县发展的关联维度全面铺开&#xff0c;核心涵盖景区创建可行性、发展影响及优化路径三大核心方向&#xff0c;同时兼顾区域差异与实践导向。可研究区县现有旅游资源禀赋与 5A 景区评定标准的匹…

作者头像 李华
网站建设 2026/5/1 7:21:34

串级PID控制3508(2)(单环角度环+单环角速度环+串级PID)

这篇PID的调制就知识我自己个人对于PID的理解了&#xff0c;看了B站好多大佬的视频所以有问题请大家见谅&#xff0c;也请大家多多指正。 这里给大家介绍一个学习PID现象的网页 https://pid-simulator-web.skythinker.top/ 首先我们要知道&#xff0c;DJM3508C620电调的反馈值…

作者头像 李华
网站建设 2026/4/18 23:31:24

KCD Beijing + vLLM 2026 议题征集中!

Kubernetes AI 大模型推理&#xff0c;一场社区共创的技术盛会当 Kubernetes 成为 AI 基础设施的事实标准&#xff0c;当 大模型推理进入工程化与规模化阶段&#xff0c;云原生与 AI&#xff0c;正在真正走向融合。于是&#xff0c;KCD Beijing 与 vLLM 社区 决定一起做一件事…

作者头像 李华