对象的生离死别

对象的生离死别

实验介绍

在构建一个类时,一般情况下需要编写构造函数、拷贝构造函数以及析构函数,这将直接影响程序的运行。而初始化列表是在调用构造函数时初始化参数的方式。

一个对象从实例化到销毁的历程:

知识点
  • 内存分区
  • 构造函数
  • explicit 关键字
  • 初始化列表
  • 拷贝构造函数
  • 析构函数

内存分区

介绍

根据存储数据的类型,系统将不同类型的数据存储在不同的区域,作为 C++ 开发者,必须对内存的分区以及使用了然于心。

分区

一般情况下,根据内存用途将内存划分为五个区:

内存区用途解释
栈区存储函数的参数、局部变量等
堆区由程序员分配、释放内存
全局区存储全局变量和静态变量
常量区存储常量
代码区存储逻辑代码的二进制
栈与堆对比
功能
申请与释放编译器自动分配、回收程序员分配和释放(C 使用 malloc 申请内存、free 释放内存;C++ 使用 new 申请内存、delete 释放内存)
申请内存后系统的响应申请空间大于栈空间时程序将提示异常 (栈溢出)超过内存空间程序报异常
空间大小限制window 1 M / linux 8 M系统内存,比栈大很多
申请效率比较慢(只是相对栈,实际也很快)
示例代码 1
#include <iostream>
using namespace std;

class Plan
{
    // 默认为私有属性
    int wingCount;
public:
    // 代码区
    Plan() { wingCount = 0; }
    ~Plan() {}
    int getWingCount() { return wingCount; }
};

int main()
{
    // 栈上
    Plan p1;
    Plan p2;
    Plan p3;
    p1.getWingCount();
    p2.getWingCount();
    p3.getWingCount();
    return 0;
}

代码解释
  • 编译时 getWingCount 只存储一份。
  • 实例化的对象 p1p2p3 存储在栈上。
  • 当对象调用 getWingCount 成员函数只需要找到相应地址即可。
  • 当变量没有被初始化时是一个随机值,建议所有变量都初始化。
  • 示例代码 1 中数据在类默认私有属性区域,但一般建议添加封装属性关键字。

构造函数

定义:构造函数又称构造方法、建构子、构造器,是类里用于创建对象的特殊子程序。可以初始化一个新建的对象,并时常接受参数用以设定实例变量。

规则与特点
  • 对象实例化时自动被调用。
  • 与类名同名。
  • 没有返回值。
  • 可以有多个重载形式。
  • 实例化对象时仅用到一个构造函数。
  • 当用户没有定义构造函数时,编译器自动生成。
示例代码 2
#include <iostream>
#include <string>
using namespace std;

class Teacher
{
public:
    // 1. 无参构造函数
    Teacher() {}
    // 2. 有参构造函数
    Teacher(string name, int age) {
        this->name = name;
        this->age = age;
    }
    // 3. 有参构造函数--全部有默认参数-->默认构造函数
    /*Teacher(string name = "jake", int age = 15) {
        this->name = name;
        this->age = age;
    }*/
private:
    string name;
    int age;
};

注意:

  • 根据重载函数的规则,例如示例代码 2 中有参构造函数与缺省构造函数不能同时使用,因为参数的个数和类型都是相同的。
  • 示例代码 2 中无参构造函数与缺省构造函数也不能同时使用,因为编译器无法识别是使用无参构造函数还是使用缺省函数。
  • 如果实例化对象不需要传递参数的构造函数统称默认构造函数。
explicit 关键字

作用:指定构造函数或转换函数或推导指引为显示,即不能用于隐式转换赋值初始化。默认情况下类构造函数为 implicit(隐式)。

在讲解构造函数时需要提到 explicit 关键字,因为很多时候会使用到 explicit 关键字。

示例代码 3
#include <iostream>
#include <string>
using namespace std;

class A
{
public:
    // 默认 implicit(隐式转换)
    A(int) { }      // 转换构造函数
    A(int, int) { } // 转换构造函数 (C++11)
    operator bool() const { return true; }
};

class B
{
public:
    // 申明构造函数使用显示声明,不能隐式转换
    explicit B(int) { }
    explicit B(int, int) { }
    explicit operator bool() const { return true; }
};

int main()
{
    A a1 = 1;      // OK赋值初始化选择 A::A(int)
    A a2(2);       // OK:直接初始化选择 A::A(int)
    A a3 {4, 5};   // OK:直接列表初始化选择 A::A(int, int)
    A a4 = {4, 5}; // OK赋值列表初始化选择 A::A(int, int)
    A a5 = (A)1;   // OK:显式转型进行 static_cast
    if (a1) ;      // OK:A::operator bool()
    bool na1 = a1; // OK赋值初始化选择 A::operator bool()
    bool na2 = static_cast<bool>(a1); // OK:static_cast 进行直接初始化

//  B b1 = 1;      // err赋值初始化不考虑 B::B(int)
    B b2(2);       // OK:直接初始化选择 B::B(int)
    B b3 {4, 5};   // OK:直接列表初始化选择 B::B(int, int)
//  B b4 = {4, 5}; // err赋值列表初始化不考虑 B::B(int,int)
    B b5 = (B)1;   // OK:显式转型进行 static_cast
    if (b2) ;      // OK:B::operator bool()
//  bool nb1 = b2; // err赋值初始化不考虑 B::operator bool()
    bool nb2 = static_cast<bool>(b2); // OK:static_cast 进行直接初始化
}

  • 防赋值初始化时使用 explicit 关键字
  • 防赋值列表初始化时使用 explicit 关键字

拷贝构造函数

  • 语法格式:类名(const 类名 &变量)
  • 如果没有自定义构造函数,系统自动生成。
  • 采用直接初始化或赋值初始化实例化对象时系统自动调用拷贝构造函数。
示例代码 4
#include <iostream>
#include <string>
using namespace std;

class Teacher
{
public:
    // 1. 无参构造函数
    Teacher() {}
    // 2. 有参构造函数
    Teacher(string name, int age) {
        this->name = name;
        this->age = age;
    }
    // 3. 拷贝构造函数
    Teacher(const Teacher &tea) {
        this->name = tea.name;
        this->age = tea.age;
    }
private:
    string name;
    int age;
};

int main()
{
    // 执行默认构造函数
    Teacher tea1;
    // 执行拷贝构造函数
    Teacher tea2 = tea1;
    Teacher tea3 = Teacher(tea1);

    return 0;
}

注意:

  • 拷贝构造函数也是构造函数的一种,当执行了拷贝构造函数后就不会执行其他构造函数。
  • 如果不涉及深拷贝,可以不实现拷贝默认构造函数,使用系统自动生成的拷贝构造函数即可。

初始化列表

  • 先于构造函数执行。
  • 只能用于构造函数。
  • 可以同时初始化多个数据成员,多个数据成员之间使用逗号隔开。
示例代码 5
#include <iostream>
using namespace std;

class Circle
{
public:
    Circle() : Pi(3.14) {}
    // 错误:Circle() { Pi = 3.14; }
private:
    const double Pi;
};

注意:

  • 语法格式:类名() : 数据成员 1(参数), 数据成员 2(参数) {}
  • 由于初始化列表先于构造函数执行,当类中有 const 常量时就必须要用到初始化列表来初始化。
  • 推荐使用初始化列表的方式来初始化数据成员。
  • 如果类中有数据成员时,推荐将数据成员都初始化。

析构函数

析构函数是在对象销毁时自动调用的函数,一般将释放内存的工作放在析构函数中完成。

  • 语法格式:~类名()
  • 析构函数不允许有任何参数、不允许重载、没有返回值。
  • 如果没有自定析构函数,系统自动生成。
  • 对象销毁时自动调用。
示例代码 6
#include <iostream>
using namespace std;

class Student
{
public:
    Student() : buffer(new char[16]) {}
    ~Student() {
        // 析构函数释放内存
        delete [] buffer;
        buffer = nullptr;
    }
private:
    char *buffer;
};

实验总结

类定义要素
  • 一个好的构造函数、拷贝构造函数和析构函数可以使程序使用更加稳健。
  • 在编写构造函数时需要考虑是否使用 explicit 关键字修饰。
  • 推荐在编写程序时使用初始化列表的方式初始化参数。
  • 析构函数时要注意释放堆中的内存,但也要注意避免重复释放内存造成程序崩溃。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/236832.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IP定位数据可能不准的原因有哪些

IP定位数据可能不准的原因有多种&#xff0c;主要包括以下几个方面&#xff1a; 动态IP地址&#xff1a;一些互联网服务提供商(ISP)会为用户分配动态IP地址&#xff0c;这意味着用户的IP地址可能会随时间而变化。因此&#xff0c;数据库中的位置信息可能不时过时。 代理服务器…

视频如何提取文字?这四个方法一键提取视频文案

视频如何提取文字&#xff1f;你用过哪些视频提取工具&#xff1f;视频转文字工具&#xff0c;又称为语音识别软件&#xff0c;是一款能够将视频中的语音或对话转化为文字的实用工具。它运用了尖端的声音识别和语言理解技术&#xff0c;能精准地捕捉视频中的音频&#xff0c;并…

当视觉遇到毫米波雷达:自动驾驶的三维目标感知基准

​ 文章&#xff1a;Vision meets mmWave Radar: 3D Object Perception Benchmark for Autonomous Driving 作者: Yizhou Wang, Jen-Hao Cheng, Jui-Te Huang , Sheng-Yao Kuan , Qiqian Fu , Chiming Ni 编辑&#xff1a;点云PCL 欢迎各位加入知识星球&#xff0c;获取PDF…

Web安全-SQL注入【sqli靶场第11-14关】(三)

★★实战前置声明★★ 文章中涉及的程序(方法)可能带有攻击性&#xff0c;仅供安全研究与学习之用&#xff0c;读者将其信息做其他用途&#xff0c;由用户承担全部法律及连带责任&#xff0c;文章作者不承担任何法律及连带责任。 0、总体思路 先确认是否可以SQL注入&#xff0…

Q_GDW1819-2013电压监测装置协议结构解析

目录 一 专业术语二 基本功能2.1 基础功能2.2 数据存储2.3 显示功能&#xff08;设备能够看到的&#xff09;2.4 参数设置与查询2.5 事件检测与告警功能 三 其他内容3.1 通信方式3.2 通信串口 四 帧结构解析4.1 传输方式4.2 数据帧格式4.2.1 报文头&#xff08;2字节&#xff0…

wvp gb28181 pro 配置https访问

准备工作 必须要有域名。虽然数字证书也有ip证书,但是会很麻烦,多数ca机构验证服务器需要用到80或443端口,也就是必须先备案,所以最好还是使用域名证书。购买域名证书。根据安全级别要求自行配置。单域名(不支持通配符的),阿里云的域名都是可以免费申请的。完成域名到服…

2024美赛备战1--数据处理(数据预处理,异常值处理,预测模型,插值拟合 *****必看****)

1.数据预处理 所谓数据预处理&#xff0c;就是指在正式做题之前对数据进行的一些处理。在有些情 况下&#xff0c;出题方提供的数据或者网上查找的数据并不能直接使用&#xff0c;比如缺少数据甚 至是异常数据&#xff0c;如果直接忽略缺失值&#xff0c;或者没发现异常数据&am…

Axure RP 9 入门教程

1. Axure简介 Axure 是一个交互式原型设计工具&#xff0c;可以帮助用户创建复杂的交互式应用程序和网站。Axure 能够让用户快速构建出具有高度可交互性的原型&#xff0c;可以在团队中进行协作、分享和测试。 使用 Axure 可以设计出各种不同类型的原型&#xff0c;包括网站、移…

企业网站运营不稳定有什么影响

如果一个公司的网站打开都有困难&#xff0c;那么用户会对这个企业的实力产生怀疑&#xff0c;企业网站除了作为企业的名片外&#xff0c;更多的是承担增加企业交易订单的任务。因此很多网站会做有关的网络广告或者搜索引擎优化的工作。如果网站无法正常打开&#xff0c;那么用…

HNU计算机体系结构-实验3:多cache一致性算法

文章目录 实验3 多cache一致性算法一、实验目的二、实验说明三 实验内容1、cache一致性算法-监听法模拟2、cache一致性算法-目录法模拟 四、思考题五、实验总结 实验3 多cache一致性算法 一、实验目的 熟悉cache一致性模拟器&#xff08;监听法和目录法&#xff09;的使用&am…

类人智能体概念、能力与衍生丨AI Agents闭门研讨观点集锦

导读 在智源社区举办的「青源Workshop第27期&#xff1a;AI Agents 闭门研讨会」上&#xff0c;来自英伟达的高级应用科学家王智琳、CAMEL一作李国豪、AutoAgents一作陈光耀&#xff0c;以及相关技术专家们共同参与交流讨论&#xff0c;分享了最新的研究成果&#xff0c;共同探…

【UE5】初识MetaHuman 创建虚拟角色

步骤 在UE5工程中启用“Quixel Bridge”插件 打开“Quixel Bridge” 点击“MetaHumans-》MetaHuman Presets UE5” 点击“START MHC” 在弹出的网页中选择一个虚幻引擎版本&#xff0c;然后点击“启动 MetaHuman Creator” 等待一段时间后&#xff0c;在如下页面点击选择一个人…

mysql:建议使用INT UNSIGNED类型存储IPv4地址

建议使用INT UNSIGNED类型存储IPv4地址&#xff0c;而不要使用INT类型&#xff0c;也不建议使用VARCHAR(15)类型存储。 在mysql中&#xff0c;内嵌函数INET_ATON(expr)可以将IP地址字符串转换为整数&#xff0c;内嵌函数INET_NTOA(expr)可以将整数转换为ip地址字符串。 例如&a…

【基础知识】SAR成像:从背景到应用的全方位概述

最近有项目接触到SAR成像图像&#xff0c;为了对SAR有一个全面的认识&#xff0c;本文结合自身研究经验&#xff0c;从背景到应用做一下简要概述。 背景 SAR&#xff08;Synthetic Aperture Radar&#xff0c;合成孔径雷达&#xff09;成像是一种先进的雷达技术&#xff0c;…

Kalman滤波、扩展Kalman滤波、无迹Kalman滤波和异步滤波的原理及其Matlab代码

目录 引言Kalman滤波代码及其结果展示 扩展Kalman滤波代码及其结果展示 无迹Kalman滤波无迹变换无迹Kalman滤波代码及其结果展示 异步无迹Kalman滤波原理代码及其结果展示 引言 本文给出了Kalman Filter&#xff08;卡尔曼滤波&#xff09;、Extended Kalman Filter&#xff0…

新零售模式:跨境电商如何实现线上线下融合?

随着数字时代的发展&#xff0c;新零售模式逐渐崭露头角&#xff0c;成为跨境电商发展的重要趋势。线上线下融合不仅拓宽了销售渠道&#xff0c;更提供了更丰富、更便捷的购物体验。 本文将深入探讨新零售模式在跨境电商中的应用&#xff0c;以及如何实现线上线下融合&#xf…

测距传感器

测距传感器 电子元器件百科 文章目录 测距传感器前言一、测距传感器是什么二、测距传感器的类别三、测距传感器的应用实例四、测距传感器的作用原理总结前言 测距传感器广泛应用于自动化控制、机器人导航、无人驾驶、测量仪器等领域。不同类型的测距传感器具有不同的测距范围、…

ASP.NET Core 8 在 Windows 上各种部署模型的性能测试

ASP.NET Core 8 在 Windows 上各种部署模型的性能测试 我们知道 Asp.net Core 在 windows 服务器上部署的方案有 4 种之多。这些部署方案对性能的影响一直以来都是靠经验。比如如果是部署在 IIS 下&#xff0c;那么 In Process 会比 Out Process 快&#xff1b;如果是 Self Hos…

从零开始搭建企业管理系统(六):RBAC 权限管理设计

RBAC 权限管理设计 前言权限分类功能权限设计什么是 RBACRBAC 组成RBAC 模型分类基本模型RBAC0角色分层模型RBAC1角色限制模型RBAC2统一模型RBAC3 RBAC0 权限设计用户管理角色管理权限管理关联表 总结 前言 作为一个后台管理系统&#xff0c;权限管理是一个绕不开的话题&#…