C++类与对象深度解析(一):从引用、内联函数到构造析构的编程实践

目录

一.引用

引用的特征:1.引用必须初始化

2.本质是别名

3.函数参数传递

4.常引用

5.函数返回值

6.权限 放大 缩小 平移

引用 vs 指针

二.内联函数

关键点说明

三.宏函数

四.类

什么是类?

简单的类

五.构造函数与析构函数

1. 构造函数(Constructor)

使用环境:

2. 析构函数(Destructor)

作用

示例

总结

六.this指针

1. 什么是 this 指针?

2. 为什么需要 this 指针?

3. 注意事项

七.拷贝构造函数

一、什么是拷贝构造函数?

二、浅拷贝(Shallow Copy)

什么是浅拷贝?

浅拷贝的问题

三、深拷贝(Deep Copy)

什么是深拷贝?

深拷贝解决方案

四、关键总结


一.引用

引用:引用不是新定义一个量而是给已存变量取一个别名,它和它引用的变量共用一块空间

引用的特征:

1.引用必须初始化

引用必须在声明时初始化,且不能重新绑定到其他对象。

int x = 10;
int &ref = x;  // 正确:引用必须初始化
// int &ref2;  // 错误:未初始化的引用
2.本质是别名

引用是变量的另一个名字,没有独立的内存地址,操作引用等价于操作原变量。

int x = 10;
int &ref = x;  // 正确:引用必须初始化
// int &ref2;  // 错误:未初始化的引用
3.函数参数传递

引用常用于函数参数,避免拷贝开销且允许修改实参(替代指针的简洁语法)。

void swap(int &x, int &y) {int temp = x;x = y;y = temp;
}int main() {int a = 1, b = 2;swap(a, b);  // 直接传递变量,无需取地址cout << a << " " << b;  // 输出 2 1
}
4.常引用

常引用可以绑定到临时对象或字面量,且不能通过引用修改原对象

const int &r1 = 42;  // 正确:常引用可绑定到字面量
int x = 10;
const int &r2 = x;   // 正确:r2 是 x 的只读别名
// r2 = 20;          // 错误:不能通过常引用修改值
5.函数返回值

引用可以作为函数返回值,但需确保返回的对象生命周期有效(避免悬空引用)。

int global = 100;int& getGlobal() {return global;  // 返回全局变量的引用(安全)
}int& dangerous() {int local = 50;return local;   // 错误:返回局部变量的引用(悬空引用)
}
6.权限 放大 缩小 平移
int main()
{//权限不能放大//const int a = 0;//int& b = a;//可以只是一个拷贝const int c = 0;int d = c;//引用过程中权限可以平移或者缩小int x = 0;int& y = x;//权限的平移const int& z = x;//权限的缩小++x;//可以,因为上面是缩小了z的权限//不可以++z;double dd = 1.11;int ii = dd;//  不可以   int& rii = dd;const int& rii = dd;//临时变量具有常性return 0;
}
引用 vs 指针
特性引用指针
初始化必须初始化可以声明后赋值
重新绑定不能可以
空值不能为空可以为 nullptr
内存占用无独立内存地址有自己的内存地址
语法简洁性直接操作对象(无需 * 或 ->需要解引用操作符(* 或 ->

二.内联函数

内联函数建议编译器将函数体直接插入调用位置(类似宏展开),以减少函数调用的开销(压栈、跳转、返回等)。适用于短小且频繁调用的函数。

#include <iostream>// 1. 使用 inline 关键字声明内联函数
inline int add(int a, int b) {return a + b;
}// 2. 类内定义的成员函数默认是内联的
class Calculator {
public:int multiply(int a, int b) {  // 隐式内联return a * b;}inline int subtract(int a, int b) {  // 显式内联return a - b;}
};int main() {int x = 5, y = 3;// 调用内联函数 addstd::cout << "加法结果: " << add(x, y) << std::endl;  // 编译器可能直接替换为 x + yCalculator calc;// 调用类内联函数std::cout << "乘法结果: " << calc.multiply(x, y) << std::endl;std::cout << "减法结果: " << calc.subtract(x, y) << std::endl;return 0;
}
关键点说明
  1. inline 关键字
    用于建议编译器将函数内联,但最终是否内联由编译器决定(可通过编译器优化选项控制,如 -O2)。

  2. 类成员函数的内联性

    • 在类内部直接定义的成员函数(如 multiply)默认是内联的。
    • 也可以在类外定义成员函数时使用 inline 关键字(需在头文件中实现)。
  3. 适用场景

    • 函数体短小(如 1-3 行代码)。
    • 频繁调用且对性能敏感的场景(如循环中的操作)。
  4. 注意事项

    • 避免内联复杂函数(如递归函数或包含循环的函数)。
    • 内联函数定义必须对调用者可见,通常直接写在头文件中。

三.宏函数

 优点-- 不需要建立栈帧,提高调用效率
 缺点-- 复杂,容易出错、可读性差、不能调试

举例三个问题的宏函数

Add(a | b, a & b); // (a | b + a & b)

为例:
以下三个有问题:

#define Add(int x, int y) return (x+y);
#define Add(x, y) x+y
#define Add(x, y) (x+y)

原因:(+ 与- 的优先级大于| 与&)

成功示范:
 

#define Add(x, y) ((x)+(y))

四.类

什么是类?
  • 是对象的“蓝图”或“模板”,用于定义对象的属性(成员变量)行为(成员函数)
  • 通过类可以创建具体的对象(实例),每个对象拥有独立的属性值。
  • 类的核心思想是封装:将数据和对数据的操作绑定在一起,并控制外部对数据的访问权限。

简单的类
#include <iostream>
using namespace std;// 定义一个 Person 类
class Person {
public: // 公有成员,外部可以直接访问char name;  // 成员变量:姓名int age;      // 成员变量:年龄// 成员函数:显示信息void display() {cout << "姓名: " << name << ", 年龄: " << age << endl;}
};int main() {// 创建 Person 类的对象Person person1;// 设置对象的属性person1.name = "张三";person1.age = 25;// 调用对象的方法person1.display(); // 输出:姓名: 张三, 年龄: 25return 0;
}

封装:通过 private 隐藏内部细节,通过 public 提供安全接口

五.构造函数与析构函数

1. 构造函数(Constructor)

作用

  • 在对象创建时自动调用,用于初始化对象的成员变量。
  • 可以重载(定义多个不同参数的构造函数)。
  • 没有返回类型,且名称与类名相同

默认构造函数:无参构造函数,全缺省构造函数,编译器默认生成的构造函数

示例

构造函数:

class Person {
public:char name;int age;// 默认构造函数(无参数)Person() {name = "Unknown";age = 0;cout << "默认构造函数被调用" << endl;}// 带参数的构造函数Person(string n, int a) {name = n;age = a;cout << "带参数的构造函数被调用" << endl;}
};
使用环境:
int main() {Person p1;                // 调用默认构造函数Person p2("Alice", 25);   // 调用带参数的构造函数return 0;
}
2. 析构函数(Destructor)
作用
  • 在对象销毁时自动调用,用于释放对象占用的资源(如内存、文件句柄)。
  • 名称是类名前加 ~没有参数和返回类型
  • 不能重载(每个类只有一个析构函数)。
示例

析构函数:

class FileHandler {
private:FILE* file;
public:// 构造函数:打开文件FileHandler(const char* filename) {file = fopen(filename, "r");cout << "文件已打开" << endl;}// 析构函数:关闭文件~FileHandler() {if (file) {fclose(file);cout << "文件已关闭" << endl;}}
};

使用场景:
 

int main() {Person p1;                // 调用默认构造函数Person p2("Alice", 25);   // 调用带参数的构造函数return 0;
}
总结
特性构造函数析构函数
调用时机对象创建时对象销毁时
主要用途初始化成员变量释放资源(如内存、文件)
重载支持重载(多个构造函数)不支持重载(唯一析构函数)
默认生成未定义时编译器生成默认构造函数未定义时编译器生成默认析构函数

通过合理使用构造函数和析构函数,可以确保对象在生命周期内正确初始化和清理资源,避免内存泄漏和逻辑错误。

六.this指针

1. 什么是 this 指针?

在 C++ 中,this 是一个指向当前对象的指针

  • 每个类的非静态成员函数(包括构造函数和析构函数)内部都可以访问 this
  • this 指针是隐式存在的,不需要手动定义。
  • 它的类型是 ClassName*(例如,Person*Car*)。
class Person {
public:string name;void printName() {// 实际上等价于:cout << this->name << endl;cout << name << endl;}
};

2. 为什么需要 this 指针?

当你在类的成员函数中访问成员变量或调用成员函数时,编译器实际上是通过 this 指针来找到当前对象的成员
例如:

class Person {
public:string name;void printName() {// 实际上等价于:cout << this->name << endl;cout << name << endl;}
};

3. 注意事项

this 是一个指针静态函数属于类,而不是对象,因此不能使用 this。this指针是形参所以是存在栈中的

class MyClass {
public:static void staticFunc() {// this->xxx;  // 错误!静态函数没有 this}
};

七.拷贝构造函数

一、什么是拷贝构造函数?

拷贝构造函数是一个特殊的构造函数,用于通过已存在的对象创建一个新对象。当发生以下情况时会自动调用:

  1. 用已有对象初始化新对象
  2. 对象作为函数参数传递(值传递)
  3. 对象作为函数返回值(值返回)

基本语法:

ClassName(const ClassName& other);
二、浅拷贝(Shallow Copy)
什么是浅拷贝?
  • 默认的拷贝构造函数是浅拷贝
  • 直接复制成员变量的值(包括指针地址)
  • 如果类中有指针成员,会导致多个对象指向同一块内存
浅拷贝的问题
class ShallowCopy {
public:int* data;//构造函数ShallowCopy(int val) {data = new int(val); // 动态分配内存}// 默认拷贝构造函数是浅拷贝:ShallowCopy(const ShallowCopy& other) = default;//析构函数~ShallowCopy() {delete data; // 释放内存}
};int main() {ShallowCopy obj1(10);ShallowCopy obj2 = obj1; // 浅拷贝// 问题:obj1和obj2的data指向同一块内存// 当main结束时,obj2先调用析构函数释放内存// 然后obj1的析构函数会尝试释放已释放的内存 → 程序崩溃!
}
三、深拷贝(Deep Copy)
什么是深拷贝?
  • 需要手动实现拷贝构造函数
  • 为指针成员分配新的内存
  • 复制指针指向的内容,而不是复制指针地址
深拷贝解决方案
class DeepCopy {
public:int* data;DeepCopy(int val) {data = new int(val);}// 手动实现深拷贝构造函数DeepCopy(const DeepCopy& other) {data = new int(*other.data); // 分配新内存并复制值}// 注意:还需要重载赋值运算符(规则同理)DeepCopy& operator=(const DeepCopy& other) {if (this != &other) {delete data;            // 释放原有内存data = new int(*other.data); // 深拷贝}return *this;}~DeepCopy() {delete data;}
};int main() {DeepCopy obj1(20);DeepCopy obj2 = obj1; // 深拷贝// obj1.data 和 obj2.data 指向不同内存// 析构时不会出现重复释放问题
}
四、关键总结
浅拷贝深拷贝
复制内容复制指针地址复制指针指向的内容
内存安全性多个对象共享同一内存,易导致崩溃每个对象拥有独立内存,安全可靠
实现方式默认拷贝构造函数需要手动实现拷贝构造函数
适用场景无动态内存分配的简单类有指针成员或动态分配资源的类

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vsan数据恢复—vsan缓存盘故障导致虚拟磁盘文件丢失的数据恢复案例

vsan数据恢复环境&故障&#xff1a; VMware vsan架构采用21模式。每台设备只有一个磁盘组&#xff08;71&#xff09;&#xff0c;缓存盘的大小为240GB&#xff0c;容量盘的大小为1.2TB。 由于其中一台主机&#xff08;0号组设备&#xff09;的缓存盘出现故障&#xff0c;导…

开源在线考试系统开源在线考试系统:支持数学公式的前后端分离解决方案

开源在线考试系统&#xff1a;支持数学公式的前后端分离解决方案 项目介绍项目概述&#xff1a;技术栈&#xff1a;版本要求主要功能&#xff1a;特色亮点 项目仓库地址演示地址GiteeGitHub 系统效果展示教师端系统部分功能截图学生端系统部分功能截图 结语 项目介绍 项目概述…

redis解决高并发看门狗策略

当一个业务执行时间超过自己设定的锁释放时间&#xff0c;那么会导致有其他线程进入&#xff0c;从而抢到同一个票,所有需要使用看门狗策略&#xff0c;其实就是开一个守护线程&#xff0c;让守护线程去监控key&#xff0c;如果到时间了还未结束&#xff0c;就会将这个key重新s…

新数据结构(12)——代理

什么是代理 在进行操作时有时不希望用户直接接触到目标&#xff0c;这时需要使用代理让用户间接接触到目标 给目标对象提供一个代理对象&#xff0c;并且由代理对象控制着对目标对象的引用 图解&#xff1a; 代理的目的 控制访问&#xff1a;通过代理对象的方式间接的访问目…

Unity Shader Graph 2D - Procedural程序化图形之夹心圆环

前言 本文将使用Unity Shader Graph的节点来绘制一个夹心圆环,分成三部分外环、内环和中心环。通过制作一个夹心圆环能够更好地理解和实践Shader Graph中的基础节点以及思维。 创建一个Ring的Shader Graph文件,再创建一个对应的材质球M_Ring以及一个Texture2D的MainT…

缓存三大问题及其解决方案

缓存三大问题及其解决方案 1. 前言 ​ 在现代系统架构中&#xff0c;缓存与数据库的结合使用是一种经典的设计模式。为了确保缓存中的数据与数据库中的数据保持一致&#xff0c;通常会给缓存数据设置一个过期时间。当系统接收到用户请求时&#xff0c;首先会访问缓存。如果缓…

【算法】----多重背包问题I,II(动态规划)

&#x1f339;作者:云小逸 &#x1f4dd;个人主页:云小逸的主页 &#x1f4dd;Github:云小逸的Github &#x1f91f;motto:要敢于一个人默默的面对自己&#xff0c;强大自己才是核心。不要等到什么都没有了&#xff0c;才下定决心去做。种一颗树&#xff0c;最好的时间是十年前…

LeetCode-524. 通过删除字母匹配到字典里最长单词

1、题目描述&#xff1a; 给你一个字符串 s 和一个字符串数组 dictionary &#xff0c;找出并返回 dictionary 中最长的字符串&#xff0c;该字符串可以通过删除 s 中的某些字符得到。 如果答案不止一个&#xff0c;返回长度最长且字母序最小的字符串。如果答案不存在&#x…

TikTok账户安全指南:如何取消两步验证?

TikTok账户安全指南&#xff1a;如何取消两步验证&#xff1f; 在这个数字化的时代&#xff0c;保护我们的在线账户安全变得尤为重要。TikTok&#xff0c;作为全球流行的社交媒体平台&#xff0c;其账户安全更是不容忽视。两步验证作为一种增强账户安全性的措施&#xff0c;虽…

面试题之箭头函数和普通函数有什么区别?

箭头函数&#xff08;Arrow Function&#xff09;和普通函数&#xff08;Regular Function&#xff09;是 JavaScript 中两种不同的函数定义方式&#xff0c;它们在语法、上下文&#xff08;this&#xff09;、原型链等方面存在显著区别。以下是它们的主要区别&#xff1a; 1. …

Llama 3.1 本地电脑部署 Linux系统 【轻松简易】

本文分享在自己的本地电脑部署 llama3.1&#xff0c;而且轻松简易&#xff0c;快速上手。 这里借助Ollama工具&#xff0c;在Linux系统中进行大模型部署~ Llama3.1&#xff0c;有三个版本&#xff1a;8B、70B、405B Llama 3.1 405B 是第一个公开可用的模型&#xff0c;在常识…

工业安全的智能哨兵:AI如何筑起生产线的“数字防火墙“

工业安全的智能哨兵:AI如何筑起生产线的"数字防火墙" (本文共1420字,阅读约需4分钟) 去年某石化厂的反应釜压力数据出现异常波动,传统监测系统在15分钟后才发出警报——而AI模型在23秒前就已预警。这场未遂事故揭示了一个残酷现实:工业安全监测正在经历从&qu…

【Bert】自然语言(Language Model)入门之---Bert

every blog every motto: Although the world is full of suffering&#xff0c; it is full also of the overcoming of it 0. 前言 对bert进行梳理 论文&#xff1a; BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding 时间&#xff1a;…

Linux中使用Docker安装DIFY搭建本地支持库和Agent

Dify 是一款开源的大语言模型(LLM) 应用开发平台。它融合了后端即服务&#xff08;Backend as Service&#xff09;和 LLMOps 的理念&#xff0c;使开发者可以快速搭建生产级的生成式 AI 应用。即使你是非技术人员&#xff0c;也能参与到 AI 应用的定义和数据运营过程中。 然而…

开源工具推荐--思维导图、流程图等绘制

1. 前言 在工作中&#xff0c;经常要用到各种不同的工具&#xff0c;随着系统的升级&#xff0c;有些工具也在不断更新升级。这里收集整理一些好用的开源工具推荐&#xff0c;遵循以下一些基本原则&#xff1a;开源免费&#xff0c;商业工具的有效平替&#xff0c;轻量级&…

Ubuntu 下 nginx-1.24.0 源码分析 - ngx_create_pool函数

ngx_create_pool 声明在 src\core\ngx_palloc.h 中 ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log); 实现在 src\core\ngx_palloc.c 中 ngx_pool_t * ngx_create_pool(size_t size, ngx_log_t *log) {ngx_pool_t *p;p ngx_memalign(NGX_POOL_ALIGNMENT, size, lo…

ac的dhcp池里option43配错导致ap无法上线问题排查过程

dhcp池里ac地址配错&#xff0c;导致ap无法上线问题排查过程 问题&#xff1a;ap手动设置ac的ip正常注册在线&#xff0c;但dhcp获得ip和ac地址发现无法在ac上注册成功。 组网&#xff1a; ac旁路结构&#xff0c;路由器lan口地址172.16.1.1&#xff0c;开dhcp服务&#xff0…

IntelliJ IDEA中Maven配置全指南

一、环境准备与基础配置 1.1 Windows 环境下载并配置 Maven 见此篇博文&#xff1a;环境配置 1.2 IDEA配置步骤 打开设置面板&#xff1a;File → Settings → Build → Build Tools → Maven 关键配置项&#xff1a; Maven home path E:\apache-maven-3.9.9 &#xff08;…

存储区域网络(SAN)管理

存储区域网络&#xff08;Storage Area Network&#xff0c;SAN&#xff09;采用网状通道&#xff08;Fibre Channel &#xff0c;简称FC&#xff09;技术&#xff0c;通过FC交换机连接存储阵列和服务器主机&#xff0c;建立专用于数据存储的区域网络。SAN提供了一种与现有LAN连…

使用vue-office报错TypeError: ft.createElementVNode is not a function

支持多种文件(.docx、.xlsx、.xls、.pdf、.pptx)预览的vue组件库&#xff0c;支持vue2/3。也支持非Vue框架的预览。 不支持.doc、.ppt&#xff08;2003年及以前的版本&#xff09; 官网&#xff1a;https://www.npmjs.com/package/vue-office/excel?activeTabreadme 官方有实…