C++细节知识for面试

news2025/3/31 20:23:57

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 确保泄露消失

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

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

相关文章

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

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

Elasticsearch 高级

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

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

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

Leetcode 两数相除

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

人工智能图像识别Scala介绍

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

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

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

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…

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

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

从 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的改进 六、总结 …

【Linux加餐-验证UDP:TCP】-windows作为client访问Linux

一、验证UDP-windows作为client访问Linux UDP client样例代码 #include <iostream> #include <cstdio> #include <thread> #include <string> #include <cstdlib> #include <WinSock2.h> #include <Windows.h>#pragma warning(dis…

Rust vs. Go: 性能测试(2025)

本内容是对知名性能评测博主 Anton Putra Rust vs. Go (Golang): Performance 2025 内容的翻译与整理, 有适当删减, 相关数据和结论以原作结论为准。 再次对比 Rust 和 Go&#xff0c;但这次我们使用的是最具性能优势的 HTTP 服务器库---Hyper&#xff0c;它基于 Tokio 异步运…

JDBC的详细使用

1. JDBC概述 JDBC[Java Database Connectivity]是 Java 语言中用于连接和操作数据库的一套标准 API。它允许 Java 程序通过统一的方式与各种关系型数据库&#xff0c;如 MySQL、Oracle、SQL Server 等交互&#xff0c;执行 SQL 语句并处理结果。 1.1 JDBC原理 JDBC的核心原理…

瑞芯微 RKrga接口 wrapbuffer_virtualaddr 使用笔记

一、源码 官方在librga中给了很多 demo 以供参考&#xff0c;例如 imresize 操作&#xff1a; /** Copyright (C) 2022 Rockchip Electronics Co., Ltd.* Authors:* YuQiaowei <cerf.yurock-chips.com>** Licensed under the Apache License, Version 2.0 (the &qu…

【数据结构】[特殊字符] 并查集优化全解:从链式退化到近O(1)的性能飞跃 | 路径压缩与合并策略深度实战

并查集的优化 导读一、合并优化1.1 基本原理1.2 按大小合并1.3 按秩合并1.4 两种合并的区别**1.4.1 核心目标****1.4.2 数据存储****1.4.3 合并逻辑****1.4.4 树高控制****1.4.5 适用场景****1.4.6 路径压缩兼容性****1.4.7 极端案例对比****1.4.8 小结**二、查找优化2.1 路径压…