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

C++细节知识for面试

1. linux上C++程序可用的栈和堆大小分别是多少,为什么栈大小小于堆?

1. 栈(Stack)大小

栈默认为8MB,可修改。

为什么是这个大小

  • 安全性:限制栈大小可防止无限递归或过深的函数调用导致内存耗尽。
  • 多线程优化:每个线程的栈独立,较小的默认值避免内存浪费(线程数多时,总内存消耗可能激增)。

2. 堆(Heap)大小

  • 默认限制

    • 堆的大小受限于系统的虚拟内存地址空间物理内存+交换空间(Swap)​
    • 在64位系统上,理论最大值为 ​128 TB​(Linux内核默认配置),实际受物理资源和进程地址空间限制。
    • 在32位系统上,通常最大为 ​3 GB​(受限于用户空间地址范围)。
  • 为什么是这个大小

  • 动态分配灵活性:堆用于动态内存分配,需支持程序运行时按需扩展。
  • 操作系统虚拟内存管理:64位系统地址空间极大,但实际分配取决于物理内存和Swap。

2. 构造函数和析构函数可以声明为inline吗,为什么?

1. 语法可行性

  • 可以声明为 inline:C++标准允许构造函数和析构函数声明为 inline

  • 隐式 inline:在类定义内部直接实现的构造函数和析构函数,默认会被编译器视为 inline,无需显式声明。

  • 显式 inline:在类外定义时,需显式添加 inline 关键字。

2. 最佳实践

  1. 优先隐式 inline:在类定义内直接实现简单的构造函数/析构函数。
  2. 避免复杂逻辑:若构造/析构函数涉及动态内存、虚函数或异常,避免内联。

总结

  • 可以声明为 inline:语法支持且对简单场景有效。
  • 需谨慎使用:复杂逻辑或涉及虚函数时,内联可能适得其反。
  • 依赖编译器决策:最终是否内联由编译器优化策略决定。

3. 函数作用域结束后,变量的析构,是有谁来进行的?

在 C++ 中,​函数作用域结束后,变量的析构是由编译器自动插入的代码触发的

编译器如何实现自动析构?

  1. 代码插入:编译器在作用域结束处(如 } 前)插入析构函数调用。
  2. 异常安全:即使作用域因异常提前退出,编译器仍会插入析构代码(利用栈展开机制)。
  3. 逆序析构:保证对象按创建的逆序析构,避免依赖问题。

4. struct和class的区别?

struct 和 class 的内存对齐规则是完全相同的,唯一的区别在于默认的访问控制权限(struct 默认 publicclass 默认 private)。

5. atomic, mutex底层实现?

1. std::atomic 的底层实现

std::atomic 用于实现无锁(lock-free)或低竞争(low-contention)的原子操作,其性能远高于互斥锁。

​**(1) 硬件支持**
  • 原子指令:直接使用 CPU 提供的原子指令,例如:
    • x86 架构LOCK 前缀指令(如 LOCK CMPXCHG 实现 CAS)。
    • ARM 架构LDREX/STREX 指令(Load-Exclusive/Store-Exclusive)。
  • 内存屏障(Memory Barriers)​:保证内存操作的顺序性,例如 std::memory_order 相关的屏障指令。

2. std::mutex 的底层实现

std::mutex 是互斥锁,用于保护临界区,其实现依赖操作系统内核的调度。

​**(1) Linux 实现(基于 pthread_mutex_t)​**
  • 轻量级锁(Futex)​:快速用户空间互斥锁(Fast Userspace Mutex)。
    • 无竞争时:完全在用户空间通过原子操作(如 CAS)完成加锁/解锁。
    • 有竞争时:通过系统调用(futex_waitfutex_wake)挂起或唤醒线程。
  • 锁类型
    • 普通锁(PTHREAD_MUTEX_DEFAULT)​:可能死锁,无错误检查。
    • 递归锁:允许同一线程多次加锁。
    • 自适应锁:在竞争激烈时退化为内核态锁。

3. 对比与选择

特性std::atomicstd::mutex
实现基础硬件原子指令 + 可能的锁模拟操作系统内核机制(Futex/CRITICAL_SECTION)
性能无锁时极快(纳秒级)无竞争时快(约 20-50 ns),有竞争时较慢
适用场景简单原子操作(计数器、标志位)复杂临界区(需保护多步操作)
内存开销通常较小(与数据类型对齐)较大(需存储锁状态和等待队列)
线程阻塞无(自旋或原子操作)可能阻塞(进入内核等待)

6. 线程的挂起和执行在用户态还是内核态?

1. 两种情况

  • 内核级线程:挂起和执行由内核态管理,是现代操作系统的默认选择(如Linux的pthread)。
  • 协程:完全在用户态实现,适用于高并发但需结合多线程利用多核。

2. 内核级线程(Kernel-Level Threads, KLT)​

  • 管理方式:由操作系统内核直接支持,每个线程是内核调度的基本单位(如Linux的pthread)。
  • 挂起与执行
    • 内核态操作:线程的创建、销毁、调度(挂起/恢复)需通过系统调用,由内核完成。
    • 内核感知:内核直接管理线程状态(就绪、运行、阻塞等)。
  • 优点
    • 并行性:线程可分配到不同CPU核心并行执行。
    • 阻塞隔离:一个线程阻塞不会影响同一进程内其他线程。
  • 缺点
    • 切换开销大(需切换到内核态)。
    • 线程数量受内核限制。

3. 协程(Coroutine)——用户态的轻量级并发

  • 管理方式:完全在用户态由程序或运行时库(如Golang的goroutine)控制。
  • 挂起与执行
    • 用户态切换:协程主动让出(yield)或恢复(resume),不依赖内核调度。
    • 非抢占式:协程需显式让出CPU,通常与事件循环(如epoll)配合。
  • 适用场景:高并发I/O密集型任务(如网络服务器)。

7. 谈一谈new/delete和malloc/free的区别和联系?

1. 核心区别

特性new/delete (C++ 运算符)malloc/free (C 标准库函数)
语法与类型安全是运算符,无需类型转换(自动匹配类型)是函数,需显式类型转换(返回 void*
构造函数/析构函数调用构造函数(new)和析构函数(delete不调用构造函数/析构函数
内存大小计算自动根据类型计算内存大小(如 new int需手动计算(如 malloc(sizeof(int)*n)
异常处理失败时抛出 std::bad_alloc 异常失败时返回 NULL(需手动检查)
内存来源自由存储区(free store)​分配堆(heap)​分配
重载支持可重载类的 operator new/delete不可重载
内存对齐自动满足类型的对齐要求需手动处理对齐(如 aligned_alloc
多态支持支持(通过虚析构函数正确释放派生类对象)不支持(需手动管理派生类内存)
扩展功能支持 placement new(在指定内存构造对象)不支持
与 C++ 特性结合兼容智能指针(如 std::unique_ptr需额外封装才能安全使用

8. 解决内存泄漏?

**(1) 使用 Valgrind 检测泄露**
valgrind --leak-check=full --show-leak-kinds=all ./your_program
  • 输出示例
    ==12345== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
    ==12345==    by 0x123456: main (main.c:10)
**(2) 分析代码**

定位到泄露位置后,检查以下常见原因:

  • 忘记释放内存malloc/new 未配对 free/delete
  • 异常路径未释放:如 return 或 throw 前未释放资源。
  • 循环引用​(智能指针):std::shared_ptr 循环引用导致无法自动释放。
​**(3) 修复并验证**
  • 修复代码:添加释放逻辑或使用 RAII(如 std::unique_ptr)。
  • 重新测试:重复步骤 1 确保泄露消失

相关文章:

C++细节知识for面试

1. linux上C程序可用的栈和堆大小分别是多少,为什么栈大小小于堆? 1. 栈(Stack)大小 栈默认为8MB,可修改。 为什么是这个大小: ​安全性:限制栈大小可防止无限递归或过深的函数调用导致内存…...

Appium中元素定位的注意点

应用场景 了解这些注意点可以以后在出错误的时候,更快速的定位问题原因。 示例 使用 find_element_by_xx 或 find_elements_by_xx 的方法,分别传入一个没有的“特征“会是什么结果呢? 核心代码 driver.find_element_by_id("xxx") drive…...

污水处理厂人员定位方案-UWB免布线高精度定位

1. 方案概述 本方案采用免布线UWB基站与北斗卫星定位融合技术,结合UWBGNSS双模定位工卡,实现污水处理厂室内外人员高精度定位(亚米级)。系统通过低功耗4G传输数据,支持实时位置监控、电子围栏、聚集预警、轨迹回放等功…...

蓝桥刷题note11(好数)

1,好数 一个整数如果按从低位到高位的顺序,奇数位 (个位、百位、万位 ⋯⋯ ) 上的数字是奇数,偶数位 (十位、千位、十万位 ⋯⋯ ) 上的数字是偶数,我们就称之为 “好数”。 给定一个正整数 NN,请计算从 1 到 NN 一共…...

Elasticsearch 高级

Elasticsearch 高级 建议阅读顺序: Elasticsearch 入门Elasticsearch 搜索Elasticsearch 搜索高级Elasticsearch高级(本文) 1. nested 类型 1.1 介绍 Elasticsearch 中的 nested 类型允许你在文档内存储复杂的数据结构,比如一个…...

SQL Server 2022常见问题解答

以下是SQL Server 2022的常见问题解答,按主题分类整理: 一、安装与升级 SQL Server 2022的系统要求是什么? 支持的操作系统:Windows Server 2016及以上、Linux(Ubuntu 20.04/22.04, RHEL 8/9等)。内存:至少4GB(建议8GB+)。磁盘空间:6GB以上,具体取决于安装组件。如何…...

基于LLM的实时信息检索汇总分析系统

基于用户需求和技术发展趋势,设计基于LLM的实时信息检索汇总分析系统,方案如下: 一、系统架构设计 1. 分层多模态数据采集层 动态渲染适配引擎 采用混合爬虫技术: 静态页面:优化Scrapy框架,集成XPath模板库…...

C语言笔记数据结构(链表)

希望文章能对你有所帮助,有不足的地方请在评论区留言指正,一起交流学习! 目录 1.链表 1.1 链表概念和组成 1.2 链表的分类 1.3 顺序表和链表 2.单链表(无头单向不循环链表) 2.1 结点的创建 2.2 创建新的结点 2.3 单链表的打印 2.4 尾…...

Leetcode 两数相除

✅ LeetCode 29. 两数相除 — 思路总览 🧩 题目要求 给定两个整数 dividend 和 divisor,实现 整数除法,不能使用乘法 *、除法 / 和取余 % 运算符。 要求返回的结果应为 向零截断的整数商,即: 正数向下取整&#xf…...

C++ 初阶总复习 (16~30)

C 初阶总复习 (16~30) 目的16. 2009. volatile关键字的作用17. 2010.什么是多态 简单介绍下C的多态18. 2011. 什么是虚函数 介绍下C中虚函数的原理19. 2012 构造函数可以是虚函数嘛20. 2013.析构函数一定要是虚函数嘛?21. 2015. 什么是C中的虚…...

Koordinator-Metric查询

以CollectAllPodMetricsLast()举例,看看koordinator怎样使用tsdb进行查询。 CollectAllPodMetricsLast() GenerateQueryParamsLast()传入metric采集间隔2倍时间调用CollectAllPodMetrics()func CollectAllPodMetricsLast(statesInformer statesinformer.StatesInformer, metr…...

人工智能图像识别Scala介绍

Scala 一.Scala 简介 Scala即Scalable Language(可伸缩的语言),Scala 语言是由 Martin Odersky 等人在 2003 年开发的,并于 2004 年首次发布。意味着这种语言设计上支持大规模软件开发,是一门多范式的编程语言。 Sc…...

PCL 点云多平面探测

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 这里实现了一种点云多平面探测的算法,该算法使用基于鲁棒统计的方法进行平面补丁检测。该算法具体过程:首先将点云细分为更小的块(使用二分法),然后尝试为每个点云块匹配一个平面。如果平面通过了鲁棒平面性测试…...

npm i 出现的网络问题

npm i 出现的网络问题 解决方案: npm config list 查看.npmrc文件中是否配置了proxy删除.npmrc文件中的proxy,保存。重新执行npm i命令。 顺便说说解决这个问题的心里路程 每次安装vue的环境的时候,经常遇到npm安装一些插件或者是依赖的时…...

C++中使用CopyFromRecordset将记录集拷贝到excel中时,如果记录集为0个,函数崩溃,是什么原因

文章目录 原因分析解决方案1. 检查记录集是否为空2. 安全调用COM方法3.进行异常捕获4. 替代方案:手动处理空数据 总结 在C中使用CopyFromRecordset将空记录集(0条记录)复制到Excel时崩溃的原因及解决方法如下: 原因分析 空记录集…...

代码随想录算法训练营--打卡day3

复习:标注感叹号的需要在电脑上重新做几遍 一.两两交换链表中的节点!! 1.题目链接 24. 两两交换链表中的节点 - 力扣(LeetCode) 2.思路 画图 3.代码 class Solution {public ListNode swapPairs(ListNode head) …...

c#的.Net Framework 的console 项目找不到System.Window.Forms 引用

首先确保是建立的.Net Framework 的console 项目,然后天健reference 应用找不到System.Windows.Forms 引用 打开对应的csproj 文件 在第一个PropertyGroup下添加 <UseWindowsForms>true</UseWindowsForms> 然后在第一个ItemGroup 下添加 <Reference Incl…...

蓝桥杯嵌入式学习笔记

用博客来记录一下参加蓝桥杯嵌入式第十六届省赛的学习经历 工具环境准备cubemx配置外部高速时钟使能设置串口时钟配置项目配置 keil配置烧录方式注意代码规范头文件配置 模块ledcubemx配置keil代码实现点亮一只灯实现具体操作的灯&#xff0c;以及点亮还是熄灭 按键cubemx配置k…...

zookeeper详细介绍以及使用

Zookeeper 是一个开源的分布式协调服务&#xff0c;提供了一个高效的分布式数据一致性解决方案。它的主要作用是维护集群中各个节点之间的状态信息&#xff0c;协调节点之间的工作&#xff0c;并处理节点宕机等故障情况。Zookeeper 的核心功能包括数据发布/订阅、分布式锁、集群…...

Blender多摄像机怎么指定相机渲染图像

如题目所说&#xff0c;当blender的场景里面有摄像机的时候&#xff0c;按F12可以预览渲染结果&#xff0c;但是当有多个摄像机的时候就不知道使用哪个进行渲染了。 之前在网上没有找到方法&#xff0c;就用笨方法&#xff0c;把所有的摄像机删除&#xff0c;然后设置自己需要…...

Redis场景问题1:缓存穿透

Redis 缓存穿透是指在缓存系统&#xff08;如 Redis&#xff09;中&#xff0c;当客户端请求的数据既不在缓存中&#xff0c;也不在数据库中时&#xff0c;每次请求都会直接穿透缓存访问数据库&#xff0c;从而给数据库带来巨大压力&#xff0c;甚至可能导致数据库崩溃。下面为…...

CSS 如何设置父元素的透明度而不影响子元素的透明度

CSS 如何设置父元素的透明度而不影响子元素的透明度 在 CSS 中&#xff0c;设置父元素的透明度&#xff08;如通过 opacity 属性&#xff09;会影响所有子元素的透明度&#xff0c;因为 opacity 是作用于整个元素及其内容的。如果想让父元素透明但不影响子元素的透明度&#x…...

Java的string默认值

在Java中&#xff0c;String类型的默认值取决于其定义和实例化的方式。 以下是关于String默认值的详细说明 未实例化的String变量‌ 如果定义一个String变量但未对其进行实例化&#xff08;即未使用new关键字或直接赋值&#xff09;&#xff0c;其默认值为:ml-search[null]。这…...

从 MySQL 到时序数据库 TDengine:Zendure 如何实现高效储能数据管理?

小T导读&#xff1a;TDengine 助力广州疆海科技有限公司高效完成储能业务的数据分析任务&#xff0c;轻松应对海量功率、电能及输入输出数据的实时统计与分析&#xff0c;并以接近 1 : 20 的数据文件压缩率大幅降低存储成本。此外&#xff0c;taosX 强大的 transform 功能帮助用…...

观察者模式:解耦对象间的依赖关系

观察者模式&#xff1a;解耦对象间的依赖关系 JDK 中曾直接提供对观察者模式的支持&#xff0c;但因其设计局限性&#xff0c;现已被标记为“过时”&#xff08;Deprecated&#xff09;。不过&#xff0c;观察者模式的思想在 JDK 的事件处理、spring框架等仍有广泛应用。下面我…...

windows第二十章 单文档应用程序

文章目录 单文档定义新建一个单文档应用程序单文档应用程序组成&#xff1a;APP应用程序类框架类&#xff08;窗口类&#xff09;视图类&#xff08;窗口类&#xff0c;属于框架的子窗口&#xff09;文档类&#xff08;对数据进行保存读取操作&#xff09; 直接用向导创建单文档…...

通信协议之串口

文章目录 简介电平标准串口参数及时序USART与UART过程引脚配置 简介 点对点&#xff0c;只能两设备通信只需单向的数据传输时&#xff0c;可以只接一根通信线当电平标准不一致时&#xff0c;需要加电平转换芯片&#xff08;一般从控制器出来的是信号是TTL电平&#xff09;地位…...

Java入门知识总结——章节(二)

ps&#xff1a;本章主要讲数组、二维数组、变量 一、数组 数组是一个数据容器&#xff0c;可用来存储一批同类型的数据 &#x1f511;&#xff1a;注意 类也可以是一个类的数组 public class Main {public static class Student {String name;int age; // 移除 unsignedint…...

Verilog 中寄存器类型(reg)与线网类型(wire)的区别

目录 一、前言 二、基本概念与分类 1.寄存器类型 2.线网类型 三、六大核心区别对比 四、使用场景深度解析 1.寄存器类型的典型应用 2. 线网类型的典型应用 五、常见误区与注意事项 1. 寄存器≠物理寄存器 2.未初始化值陷阱 3.SystemVerilog的改进 六、总结 …...

基于华为设备技术的端口类型详解

以下是基于华为设备技术网页的端口类型详解&#xff08;截至2025年3月&#xff09;&#xff1a; 一、Access端口 定义&#xff1a;仅允许单个VLAN通过&#xff0c;用于连接终端设备&#xff08;如PC、打印机&#xff09; 处理流程&#xff1a; ​接收帧&#xff1a;未带标签…...