当前位置: 首页 > news >正文

C++知识点复习(面向面试6)

今天是第六天了也是终于快复习一半了,为自己鼓鼓掌。今天依旧是五条知识点,一起来查漏补缺吧。

26.类和结构体什么区别?

27.被 deletefree释放的内存会直接返还给操作系统吗?

28.什么时候需要析构函数?

29.常函数内能否修改静态成员?

30.初始化参数列表什么特点

好的,我们从第二十六条开始。

26.类和结构体什么区别?

语法层面:只有两个默认权限不同

在 C++ 中,classstruct在功能上几乎是 100% 相同的(都可以包含成员变量、成员函数、构造/析构函数,也都支持继承和多态)。它们唯二的硬性语法区别在于:

  1. 默认访问权限不同
    • class的默认访问权限是private(私有)。
    • struct的默认访问权限是public(公开)。
  2. 默认继承权限不同
    • class继承默认是private继承。
    • struct继承默认是public继承。

27.被 deletefree释放的内存会直接返还给操作系统吗?

不会,会被存放在内存池中,下次申请内存时直接去内存池中查找,解决了内存碎片问 题。(一般公司不会问的知识点,曾经拼多多,腾讯等问过想了解搜索 ptmalloc的实现)

如何主动将内存还给操作系统?

如果面试官继续深挖:“如果程序长时间运行,产生了大量空闲内存但都没还给系统,导致进程占用内存(RSS)居高不下,该怎么办?”

  • 解决方案:可以调用 glibc 提供的非标准函数malloc_trim(0)
  • 作用:它会尝试强制将堆顶(top chunk)连续的空闲内存通过brk(-size)系统调用收缩并归还给操作系统。但需要注意,如果堆顶内存不连续(比如被一些未释放的小对象挡住),这个操作可能会失败或只能归还部分内存。、

28.什么时候需要析构函数?

需要手写析构函数的根本原因是“类内部申请了需要手动释放的资源(堆内存、文件句柄、网络连接等)”。并且,一旦手写了析构函数,一定要警惕默认的浅拷贝带来的双重释放风险,遵循“三/五法则”来完善类的拷贝和移动语义。

1. 动态分配的内存(最典型)

当类的成员变量中,有通过newnew[]或 C 语言的malloc等函数在堆区申请的内存时,必须在析构函数中使用deletedelete[]free来释放。

  • 举例:你提到的指针成员char* mName = new char[100];,如果不在析构函数中delete[] mName;,就会导致内存泄漏。

2. 系统资源句柄(极易被忽略)

除了内存,程序在运行中打开的各类系统资源,如果不关闭,会导致资源泄漏,甚至影响整个系统的正常运行。这些资源通常不是通过new分配的,但也必须在析构函数中手动关闭。

  • 打开的文件:通过fopen打开的文件指针(FILE*),需要在析构中调用fclose关闭。
  • 网络连接/数据库连接:比如 Socket 套接字、数据库连接句柄等,需要在析构中调用close或专门的断开连接函数。
  • 互斥锁/信号量:在多线程编程中,如果类持有锁,需要在析构中确保锁被正确释放,防止死锁。

3. 自定义类型成员需要特殊清理时

如果类中包含其他自定义类型的成员,且这些成员本身管理着上述资源,通常这些成员自己的析构函数会处理清理工作。但如果你需要控制它们的销毁顺序,或者进行一些额外的联动清理操作,也需要手写当前类的析构函数。

  • 补充机制:如果类中全是intdoublestd::string这种自带完善析构机制的成员,编译器生成的默认析构函数就完全够用了,此时不需要手写。

💡 面试核心加分项:析构函数与“三/五法则”

在面试中,当你回答了“什么时候需要析构函数”后,面试官紧接着大概率会追问:“如果你手写了析构函数,还需要注意什么?”

这时你可以抛出 C++ 著名的“三法则(Rule of Three)”或 C++11 后的“五法则(Rule of Five)”

  • 核心逻辑:如果你需要手写析构函数,说明你的类在手动管理资源。那么,编译器自动生成的拷贝构造函数拷贝赋值运算符(浅拷贝)大概率是错误的。
  • 潜在风险:默认的浅拷贝会导致两个对象的指针成员指向同一块堆内存。当其中一个对象被销毁(调用析构函数释放内存)后,另一个对象的指针就会变成“野指针”,再次析构时会引发重复释放(Double Free),导致程序崩溃。
  • 正确做法:一旦手写了析构函数,通常也必须显式手写(或禁用)拷贝构造函数和拷贝赋值运算符,来实现深拷贝或禁止拷贝。在 C++11 以后,还需要考虑移动构造函数和移动赋值运算符。

29.常函数内能否修改静态成员?

可以,常函数内不能修改非静态成员,因为访问非静态成员需要使用this指针,例如:在 类 A中的一个常函数内this指针的类型为 :const A* const this; *thisconst修饰代表不能 通过 this指针修改对象,我门在访问非静态成员时需要使用this指针,所以不能修改,访问静 态成员时不需要使用 this指针区分是哪个对象的成员,因为静态成员是共享的单独存放在静态 区不占对象的内存,所以常函数内可以修改静态成员。
30.初始化参数列表什么特点

●构造函数和类名相同,没有返回值也不写 void
●如果没有实现构造函数编译器会提供默认的无参构造函数
●构造函数是给成员变量赋值的不是初始化(引出初始化参数列表)
●移动构造,继承构造,委托构造(C++11后的写法,更加简洁高效)

#include <iostream> #include <string> // 1. 模拟一个没有默认构造函数的类(作为成员对象) class Engine { public: Engine(int horsepower) : m_horsepower(horsepower) { std::cout << "Engine 构造函数被调用,马力: " << m_horsepower << std::endl; } private: int m_horsepower; }; // 2. 父类(没有默认构造函数,强制子类在初始化列表中调用) class Vehicle { public: Vehicle(std::string brand) : m_brand(brand) { std::cout << "Vehicle 父类构造函数被调用,品牌: " << m_brand << std::endl; } private: std::string m_brand; }; // 3. 子类 Car,包含 const、引用、无默认构造成员 class Car : public Vehicle { public: // 构造函数:演示初始化列表的各种用法 Car(std::string brand, int hp, int& yearRef) : Vehicle(brand), // 特点5:调用父类的带参构造函数 m_engine(hp), // 特点4:调用成员对象 Engine 的带参构造函数 m_maxSpeed(220), // 特点3:const 常量必须在初始化列表中初始化 m_yearRef(yearRef) // 特点3:引用成员必须在初始化列表中绑定 { std::cout << "Car 子类构造函数体执行" << std::endl; // 注意:如果在这里写 m_maxSpeed = 220; 或 m_yearRef = yearRef; 编译器会直接报错! } void display() { std::cout << "当前引用的年份: " << m_yearRef << std::endl; } private: int m_maxSpeed; // const 常量成员 int& m_yearRef; // 引用成员 Engine m_engine; // 没有默认构造函数的成员对象 // 演示初始化顺序的坑: int m_a; int m_b; }; int main() { int currentYear = 2026; std::cout << "--- 开始创建 Car 对象 ---" << std::endl; // 传入品牌、马力、以及一个外部变量的引用 Car myCar("Tesla", 500, currentYear); myCar.display(); return 0; }
http://www.jsqmd.com/news/892137/

相关文章:

  • PP 蜂窝板回料利用与成本控制的工程化方案
  • ICT-META:基于上下文学习的加密流量少样本分类模型实践
  • 从零开始构建豆瓣Top250电影爬虫:完整教程与反爬虫实战
  • ChatGPT插件安装实操手册(2024最新版):OpenAI官方未公开的3个关键验证步骤与绕过限制技巧
  • DFS岛屿问题:核心思想与实战模板
  • Vite Tree Shaking 实战笔记
  • RK3576上electron调用GPU的功能设置方法
  • 避坑指南:大模型权重跨机传输遭遇 Broken pipe、密码错位与断点续传终极解决方案
  • 4D-STEM数据革命:py4DSTEM如何重塑材料科学分析范式
  • NAVSIM数据驱动仿真平台
  • ARM架构SError异常机制与RAS特性解析
  • pandas数据处理实战:从环境搭建到清洗分析全流程
  • 【飞机】基于matlab自主无人机飞行稳定和轨迹跟踪【含Matlab源码 15569期】
  • 开源协作机械臂OpenArm:如何用模块化设计打破机器人研发的壁垒
  • Topit:重新定义Mac窗口置顶,打造无缝多任务工作流
  • win11打开软件,显示在后台运行
  • 个人助理工作流重构
  • 从文件柜视角解析RAG:构建高效检索增强生成系统的工程实践
  • 文件无法保存,改如何解决呢?
  • BotW-Save-Manager深度解析:跨平台存档转换技术实现
  • Taotoken用量看板如何帮助个人开发者清晰掌控月度支出
  • 网络安全的现状如何了?怎么看待如今的网络安全圈子?
  • 如何高效使用Kohya_SS:稳定扩散模型训练实战指南
  • 靠谱的TIG热丝堆焊设备厂家
  • AI工具选型黄金窗口期(2024Q3–2025Q2决策定成败):Gartner认证的5维评估模型首次公开
  • 绝缘绕组线击穿电压试验装置:检测漆包、膜包圆线和各种规格扁线耐击穿电压性能
  • MK60DN512VLL10 芯片解密详解
  • Lovable功能更新计划深度拆解(仅限早期测试团队内部披露)
  • ORACLE数据库查询用户表空间使用率
  • 学术写作生死线:ChatGPT引用格式错误率高达68.3%(基于2024年SCI论文抽检数据)