如何设计 C++ 面试题 , 有哪些需要注意的?

栏目:未来教育  时间:2023-07-11
手机版

  想考察一个 C++ 程序员,该设计什么样的面试题?应该注意哪些方面?-------------------------------------------其实题主是要去被面试 , 所以事先自己考虑下怎么设计面试题。O(∩_∩)O~

  正好最近做过很多这方面的工作,我是这样做的:

  1、首先明确 需要达到什么区分度。比如说:需要通过笔试+上机+面试 能够把应聘的人分为三个等级:不合格、新手、经验丰富三个等级

  2、将将程序员的能力分解,例如分解为:计算机基础知识、c语言基础知识、数据结构和算法、写代码阅读代码的能力、调试的能力、学习的能力......然后将第一点中得到的每个等级的程序员,需要具备的能力列出来

  3、根据各个知识点出题。简单的容易的,猥琐的,吓唬人的,上档次的,等等。这个几乎是最简单的一步了。我比较喜欢设计一些看上去简单,但是实际上正确答案不止一个的题目,这样能有较好的区分度,而且能够在面试的时候,根据题目能和应聘者有更进一步交流的话题。

  4、搞清楚公司需要什么样的程序员,比如公司急缺能干活的,或者公司急缺专家人才。根据需要组合题目。

  基本上就这样了

  来一些真实的面试问题

  昨天一位读者分享了自己的 C++ 面试经历。简单沟通后,读者双非本硕,自嘲注定就是炼狱模式。50 家公司的 C++ 面经也整理好了。本次就分享下面经。以后分享学习路线和心得。

  读者情况:双非本硕,本科机械,硕士做的软件开发课题。 学过一点点 C++,但是面试前连多态都不会写。研三经历炼狱校招,从零开始学习,数据结构和算法也是从零开始。 时间:2020 年 10 月- 2021 年 4 月 结果:几乎面试了所有大厂,收到了 13 份 offer。虽然没有进大厂,但是拿到音视频开发 offer,待遇刚好是大厂白菜价。已经很满足。 自我介绍C++ 语法左值引用与右值引用有什么区别,左值引用和右值引用的目的是什么虚函数问了好多什么是多态虚函数和纯虚函数构造函数和析构函数能不能是虚函数std::move 是什么计算机网络 TCP/IP 的连接和断开过程timewait 是什么I/O 多路复用是什么http 接口的函数用过吗操作系统 什么是线程、进程多线程和多进程的优缺点项目 Qt信号与槽实现的机制项目用的多线程是怎么实现的怎么实现通信计算机专业必读书籍汇总!自我介绍项目:有做过嵌入式项目吗 总结:应该是 KPI,他想找做嵌入式的多点自我介绍项目多线程网络编程:连接方式算法:快速排序面向对象三大思想设计模式,列举一个单例模式怎么处理多线程自我介绍项目介绍说说项目的原理面向对象设计模式非智力问题: 怎么抗压怎么处理队员之间的问题自我介绍看过哪些 C++ 的书多线程,怎么判断线程结束vector 中迭代器失效的情况虚析构函数FFmpeg 中对视频和音频的同步方法map 的内部rtmp 协议引用和指针的区别静态链接库与动态链接库的区别程序生成的过程计算机图形学: 怎么对图像进行变换,变换矩阵是什么还有其他简单的 OpenGL 问题其他忘了,,,,怎么自己实现 Qt 的信号与槽?多态TCP 和 UDP 的区别计算机图像学 什么是插值?会做数据可视化吗?其他忘了,面试官脾气不是很好,,聊一下项目CAD 软件怎么使用会不会 QT、MFC、STL介绍中望公司的情况(终于拿到第一份 offer!)

  假如定义了一个指针,后面接着一个循环并 return,会造成什么后果?(内存泄漏)其他忘了(没有问项目)知不知道 Qt5 对 OpenGL 有个支持性问题音视频切换的多线程怎么处理帧切换的问题大数据处理题:建立一个数据结构,存储 1 到 10 亿的数,要能够去重和插入(答案:用两个数组,建立二维表格)找出一个 RGB 文件中出现最多的前十种颜色直接问项目的 OpenGL 怎么绘制视频,结果回答不好被嫌弃了;死锁怎么产生的?有没有遇到过死锁问题?(多线程不是一般般的重要!)先做算法题:找出数组中次数最多的前 k 个数说下 C++ 新特性 auto变量的使用注意事项OpenGL 的着色器在每个渲染步骤是怎样的?设计模式、单例模式的线程安全问题qt 的消息传递机制HTTP 网络协议好多内容怎么实现 map<key,value> 的(key 是自定义类型)单例模式还有好多问题,几乎把计算机基础的难点都问了做富士康的工业互联网。看简历,没问技术基础。 给了 offer,但是只有 7K,其他补贴加起来只有 10K,难怪没人去

  1.C 和 C++ 的区别 2.栈和堆的区别 3.双链表和单链表的优缺点 4.面向对象三大特性:封装、继承、多态,继承的作用是什么 5.了解 Qt 和 MFC 吗 6.工作地点 7.对薪资有什么要求

  C++ 和 java 的区别描述 STL;vector 和 list 的区别最近的项目——视频播放器设计vector 存放数据的注意视频与音频同步多线程同步设计模式、工厂模式文件断点续传用英语简单描述自己的项目OOP 三大特性、继承中三个修饰符的用法C++ 的 static 关键字TCP 连接过程中客户端与服务端使用什么函数实现连接智能指针,weak_ptr 能够破坏环型引用的原理(引用计数的原理)用两个栈实现一个队列(秃头架构师面试,态度很好,叫我不要紧张。我印象深刻的一场面试之一)

  聊一下项目说下项目解决过程你有没有请教别人说下最难忘的项目经历项目简介STL、vectorQML 与 QWidget 的区别 (QML 从 2.0 版本开始向移动端靠拢)信号与槽机制、信号与槽与函数指针的比较多线程下用信号与槽的优缺点 (connect函数的第五个参数实际上是用在多线程的情况下的)socket的TCP的客户端与服务端怎么保证客户端与服务端在突然断网的情况下保证另一端知道? (饱和机制、心跳机制、看门狗机制)说说你的项目的亮点auto关键字 (不能定义数组)Qt的事件过滤器 (事件的传递是由子类往父类上传的)开放性问题:大量数据无序输入,怎么有序输出? (使用最大堆最小堆) (一面的面试官是个态度很好的年轻小哥)介绍项目组成 - 滤波器的类型 - 怎么确定使用什么滤波算法比赛过程中的团队合作事情数学建模比赛的收获上学期间最有成就感的事情Linux 中的互斥锁和XX锁简述 STL常用的排序算法以太网了解吗?网络编程职业规划家庭背景介绍音视频测评岗位的工作内容用的什么协议视频播放器、直播推流协议文件传输、视频协议相关工作讲解下用了音视频库的什么模块做两道编程题: 快速排序(函数参数只有 int array,int length)用两个线程实现循环加数深拷贝与浅拷贝区别C++OOP 三大特性多态的用法项目:视频播放器用到 FFmpeg 哪些库H264 编解码原理 运动补偿熵编码ALCode 视频解析工具的使用直播工具使用了什么服务器(地点在武汉,印象最深的一场面试,面试官很友好,给我讲了半小时的音视频岗位的优势。从此便决定了一定要做音视频开发)

  项目——视频播放器的功能 视频中的视频信息、音频信息的数据怎么存放课题中的难点C++ 智能指针 shared_ptr 的特殊用法C++ 内存管理Windows 系统怎么预防死锁怎么解决程序 crashed 问题对音视频编码的了解有几种 NAL,如果在视频中存放信息存放在哪个帧怎么设置压缩码率?C++11 什么新特性好用 多线程用队列处理数据有什么好处?用过什么数据库?多线程与多进程的区别?你认为你的优缺点是什么?没问技术问题,只问背景问题。应该是 KPIstatic 在 C 和 C++ 的用法virtual 与析构函数Linux 中用什么命令查找文件在项目中使用过多态吗用英文介绍自己的爱好项目 功能代码量花多长时间STL 怎么解决哈希冲突长二进制反转virtual 析构函数写一个多态,展示内存泄漏操作系统: 消息队列、进程消息strcpy 和 memcpy 的区别多态具体怎么定义指针、引用怎么在多态里面用的学过什么课程指针和引用的区别局部 变量与全局变量内存的分类OOP 三大特性Linux 常用命令简单聊聊直播推流工具边下边播用什么协议数据库的事务进程和线程、进程的通信方式、线程的安全问题TCP 和 UDP 的区别HTTP 的返回码怎么用两个栈实现一个队列怎么获取二叉树的高度除了 C++,学过其他语言吗MP4 包含了什么协议抖音、直播分别用什么协议TS 流有什么内容怎么传递视频信息怎么解决视频卡顿问题内存泄漏怎么排查安卓的生命周期设计模式有哪几种?单例模式有几种创建方式?Linux 的常用命令用过 shell 吗怎么通过 shell 获取 MD5 码?Linux 获取字符串的方式?建议:多了解前沿的流媒体格式!多进程多线程用过吗?Linux 命令了解吗?FFmpeg 编译过吗?音视频解码过程的格式视频播放器开发的过程OpenGL 使用的过程顶点着色器与片元着色器的不同VBO、FBO画面闪烁是什么原因造成群面,3 个候选人 1 个面试官公司介绍:世界 500 强 咨询公司 外企遇到难题以及解决方法在实习、项目中,怎么处理不属于自己工作范围内的工作职业方向规划?技术专家还是项目管理C++ 有几种构造函数STL 的迭代器失效,怎么解决C++ 与其他语言的区别?(指针、回收)智能指针的用法智能指针的使用场景:连接数据库STL 是复制性还是侵入性红黑树比AVL的优势,为何用红黑树红黑树的高度数据库的锁、事务、引擎场景题: 用户的余额显示、余额减少等,要不要用事务?用户系统,有用户ID。加入有手机号注册,怎么验证是否注册用户扩大时,怎么扩容?I/O 多路复用的理解动态规划与贪心算法的区别(背包问题分析)多线程的使用场景多线程的锁数据库为何用 SQLite进程间的数据共享怎么实现音视频同步多线程和多进程的区别Linux 常用命令?岗位必备技能是:C++ 基础、网络、数据库。是电商中台先做几道题说说从浏览器输入网站用到的协议auto addr = (type) malloc(size); memcpy(addr,"apple"); 操作系统满的时候会发生什么?MySQL 加快查询的方式Qt 信号与槽的机制为什么 new QWidget 不需要 deletevector 的内部机制编译过程虚函数表原理,虚表编译的过程new 和 malloc 的区别智能指针内部原理多线程TCP、UDP 的区别TCP 怎么保证可靠传输在一个局域网中怎么连接两台电脑?平时怎么学 C++计算机专业必读书籍汇总!简单介绍项目—— vector 怎么 clearTCP 粘包、丢包进程的通信内存泄漏智能指针Qt 实现多线程QSS 属于第几个版本视频播放器怎么音视频同步设计模式 举例工程模式Qt 的 TableWidget 和 Table View 的区别做题 多态的选择题手写 Rational 类(包括<< >>重载)介绍硕士课题项目Qt 自定义控件方法视频播放器Qt 多国语言QSS 主题样式设计模式 工厂模式的应用场景设计模式的优缺点信号与槽、和事件的区别视频与音频怎么同步介绍公司的研发方向: 应用软件开发下位机驱动开发单片机Windows 服务器开发多态及其用处静态多态包含什么类型纯虚函数虚析构函数重载与重写的区别extern "C"{}const 的作用指针和引用的区别C++11 新特性 右值引用STL哈希强制类型转换Qt 的优点、缺点Qt 的核心机制Qt Graph信号与槽的优点和缺点是什么Qt connect 函数的连接方式TCP 三次握手的过程手写代码:自定义 String 类(真的要每天都复习八股文)实习的时候做什么工作指针和引用的区别空指针、悬垂指针TCP 的三次握手部门分工: 图形引擎(C#)平台开发(java、C++)建模(C++、OpenGL)多态、虚析构函数强制类型转换类能否嵌套vector 改变容量时要注意什么对象移动unique_ptr 智能指针C++11 多线程 lock_guard 怎么自动处理的多线程怎么发送信号线程怎么退出GDB 怎么调试段错误,怎么查看栈Linux 怎么处理 core 文件Git 用过吗?多态的定义代码的处理过程、汇编的作用new 和 malloc 的区别内存的分类STL vector 的用法项目中是怎么用的Linux 用过什么指令项目都是自己做的?Qt 多线程用什么函数计网用过什么协议智能指针快速排序的思路MFC 用过吗设计模式、单例模式场景题:找出前 K 个最大元素的值(最大堆、最小堆的用法)写代码:找出数组中数量超过一半的元素int GetNum(int *array,int length) { unordered_map<int,int> mp; for(int i = 0;i<length-1;++i){ ++mp[array[i]]; } for(int i = 0;i<length-1;++i){ if(mp[array[i]] > length / 2){ return array[i]; } } return -1;//没有的话返回-1 //加入数据很大怎么办?——先排序 sort(array);//sort的原理是什么 return(array[length / 2]); C++的 sort 函数是怎么实现的?音视频:YUV 格式与 RGB 格式的区别怎么实现一个服务端连接多个客户端?auto 的类型判断发生在什么阶段(编译期) 如果是在运行期的话会发生什么问题多态的分类类型转换智能指针锁的类型,自旋锁的原理GDB 的常用命令内存的分类一个栈多大?实习的时候做的项目,举例做过的工作做的软件项目的流程单例模式的实现方法观察者模式哈希表的原理以及作用、怎么查找值计网 七层模型IP 协议三次握手和四次挥手为什么要进行四次挥手线程和进程 从 CPU 的角度区别线程和进程快速排序的思路、复杂度FFmpeg介绍视频播放器介绍研究生课题代码题:十进制字符串转十六进制字符串选几个关键字描述自己你的优点和缺点你期望的工作(应该是KPI)

  OOP 特性、虚函数内存泄漏、智能指针STL学过什么数据结构、举例二叉树的用法QT 信号与槽 原理优势自定义结构体到信号与槽要注意什么工厂模式、单例模式原理和用法锁要注意什么GDB 用过吗项目中要怎么调试代码MySQL 索引是什么了解软件架构吗?MVC 模式了解吗?怎么使用软件设计思维?是正向还是逆向?视频播放器 YUV 是怎么传递到 OpenGL 的AVFrame Parma 的意思YUV 有很多采样格式,你采用什么采样格式STL vector 和 list 的区别map 与 unordered_map 的区别(考虑到有序与否的区别、哈希函数)C++11 的 inplace_push_back 与 push_back 的区别unique_ptr 与 shared_ptr 的区别lambda 表达式、怎么捕获外部变量virtual 析构函数多继承的问题多线程与多进程的区别 内存地址空间多进程的锁 自旋锁原理怎么避免死锁socket 阻塞和非阻塞的区别TCP 中间连接的时候断开会发生什么(重传、超时、等待状态、TCP 可靠连接原理)进程内部的栈内存、堆内存、各自的增长方式双链表怎么查找倒数第二个结点OpenGL 常见的坐标系的变换顺序第 1 个面试官 写过多少行代码C++ 怎么申请连续的内存vector 怎么用C++ 的垃圾回收机制工程模式是什么,3 种工工厂模式的区别排序算法有哪些,哪些的复杂度是稳定不变的多线程自旋锁是什么数据库用过吗第 2 个面试官 视频播放器 音视频怎么同步展示同步的代码展示平衡功能项目多线程怎么同步GDB 怎么调试vector 是不是线程安全的,怎么写个线程安全的 vector数据库怎么 sipC++11 的新特性指针和引用的区别1 小时内做 3 到算法题 反转单链表找出数组中最小的K个数长整数相加讲解题目(做的不好,分析复杂度)描述 Qt 的消息传递机制Windows 消息机制有哪些做题 区别 const 指针与 const 变量引用的用法(左值引用与右值引用、引用不能改变绑定对象)多态的用法信号与槽的底层原理;信号与槽怎么做到性能优化哈希表与红黑树的对比:结构、查找Q t的多线程的信号与槽虚函数表原理构造函数调用虚函数可以吗?会发生什么?YUV 与 RGB 的区别音视频同步的方法数据库有几种范式HTTP 的底层模型用什么实现(TCP)网络的七层模型,作用、传输单位分别是什么TCP 的三次握手写一个快排;能否用非递归方式实现;什么时候复杂度最大?继承、多态的定义听过多用组合,少用继承吗Qt 的信号与槽原理,怎么了解这个原理的?进程、线程的区别,对 OS 而言有什么目的对 I、B、P 帧的了解、MOOV 的格式了解音视频的了解PTS、DTS的区别YUV 与 RGB 的区别音视频同步的方法讲下视频播放器 流程怎么使用多线程能否用一个线程实现考虑功能扩展吗毕业课题 如何采集、滤波、处理考虑数据采集中断的情况吗考虑 C/S 模式吗实习 文件传输是怎么实现的做过什么工作平时怎么学习给出一个二维 vector 表示点到原点的距离。一个五个点,5X5 的二维 vector。求从原点出发,再回到原点的最短路径,要求必须打印输出结果(条件概率)已知城市中蓝色:绿色车的比例是 15:85,目击者称看到蓝色车肇事逃逸,但是人区别蓝色和绿色的正确率是 80%。求真的是蓝色车肇事逃逸的概率(三面、四面在同一天进行。据说有的人腾讯面了六面。我止步于吃已经很满足。代码确实不会写)

  Qt、C++ 分别用过多久?代码量多少比赛中你负责什么角色OpenGL 了解的深度、在 QT 中的用法FFmpeg 的了解Qt 用过多线程、网络吗Qt 3D 了解吗实习过程中学会什么C++11 新特性;解释右值引用是为了解决什么问题?(移动语义)浅拷贝和深拷贝的区别OOP 设计原则博客有多少篇喜欢看什么书对 FFmpeg 的使用对音视频的了解对 C++ 的了解用过 C++ 的闭包吗?OpenGL 的了解其他 offer对公司文化的了解你目前的学习方式是什么?介绍一些康复器械项目C++11 的新特性 lambda 表达式多线程共享内容问题,共享对象存放在哪个空间进程与线程 多进程、多线程多进程通信的方式,有几种信号OSI 七层模型 TCP 与 UDP 的区别TCP 拥塞控制要了解 MySQL红黑树的定义手撕代码:把有序链表转为平衡二叉树 怎么遍历结点复杂度优化遍历方式虚函数 虚函数是类的定义出现还是对象的时候出现纯虚函数钻石继承为何不能出现智能指针 环型引用shared_ptr 的引用计数原理多线程的原子类型auto 关键字能给数组赋值,但是不能定义用过 Qt 的什么模块讲一下对 OOP 的理解讲一下单例模式 多线程的单例模式锁互斥量为何能够用在多线程数据库 表是否一定要有主键主键与唯一索引的区别left join ,right join,full join怎么建立索引索引怎么优化介绍家庭情况对 IT 工程师的理解实现过程的收获举例压力大的实例,压力大的时候怎么解决收了什么 offer,为什么拒了你认为手机会怎么发展举例说明你说服别人接收自己观点的一个例子虚表是怎么使用的?虚表指针存放在哪里?构造函数能否为 virtual,能否调用虚函数?coding:两数之和,非有序coding:LeetCode61 ——给定链表,按照某个规定旋转链表逻辑题:有 10 箱金子,,,,,,网络: TCP 与 UDP 的区别TCP的窗口拥塞控制OS:怎么避免死锁?下面是有一个全局变量 a 和两个线程,这两个线程同时开始并发执行各自的代码, 在两个线程都执行结束后,请问 a 的值为______ static int a = 0;线程1:for(int i=0; i<10;i++) a = a + 1;线程2:for(int i=0; i<10;i++) a = a + 1;已知公司 OA 数据库有一个员工信息表,包含员工 ID,员工姓名,入职时间,和离职时间。财务审核时发现 201803 到 201808 这 6 个月,当时所有在职员工都少发了工资,现在老板需要了解有多少人受影响需要获得补偿。请写出查询语句。实验室有 100 个瓶子,其中有一瓶装有慢性毒药(第 3 天发作),另外 99 瓶装有蒸馏水。请问至少需要多少只小白鼠才能在3天内找出哪一瓶是慢性毒药?_______只4.找出出现频率最高的前 K 个数,或者从海量数据中找出最大的前 K 个数

  5.实现排序二叉树的插入方法

  对公司的了解最近的 offer?为何不要?家庭成员、是否单身用三个词形容自己参加过的社团为何选择医学信息工程择业因素兴趣爱好学习方式自身的优势怎么完成学校到公司的过渡?OOP 三大特点STL 常用容器栈与堆的区别new 和 malloc 的区别指针和引用的区别 sizeof 的区别自增的区别内存上绑定的区别工厂方法模式TCP 三次握手内存泄漏是什么意思数据库 事务的定义、4 个特性脏读、幻读索引(数据结构、优缺点)锁的作用Linux 在文本中快速查找内容找出进程的P ID (PS)如何查看 OS 的大小(free)工作问题 举例说明遇到的难题以及解决方法列举工作上的过程说服别人接收你的观点的例子团队合作的例子你的专业是做什么的?做过窗口的信号共享吗?项目的滤波算法是什么?音视频项目的难题是什么?你的项目来源是哪里?遇到过程序崩溃的情况吗?TCP 的连接、释放过程 time_wait 状态分别是什么?分别发生在客户端和服务端的什么阶段?(终于拿到所谓大厂 offer。但是是 IT 部门,不是研发部门,在佛山。所以拒了)

  介绍康复训练系统 vector 如何处理数据数据库视频播放器 缓冲机制OpenCV 平滑操作是否用过 MySQL生产者消费者模式用过 socket 的 I/O 模型吗?多线程的用法 主线程次线程线程池怎么操作文件系统new 和 malloc 的区别介绍项目、视频播放器FFmpeg 怎么用的视频文件是什么格式,怎么存放的怎么设计视频播放器的暂停?后端是怎么处理的?进度条怎么显示的?多线程怎么用的?指针和引用的区别?在传递参数上有什么区别?函数未定义时会怎么样?怎么删除双向链表?快排的思路堆是不是二叉树写代码:用 C++ 实现全排列工作问题:如何看待加班?硕士毕业课题多线程怎么切换线程如何共享数据C/S 模式是如何处理的?用 TCP 怎么传递消息?TCP 与 UDP为何 TCP 没有 UDP 快用 UDP 怎么实现可靠的传输?算法问题: 网格中有 2 个点,怎么找到从 A 到 B 的最短路径?(用广度优先搜索) 数据库:为何索引的数据结构用 B-tree? (因为数据库主要消耗在磁盘 I/O 上,所以要优化磁盘 I/O ,如果用红黑树,树的深度太高,消耗磁盘 I/O 太多,速度会太慢)做一份笔试,问的比较细节,操作系统比较重要,几个 C语言的关键字没用过三个面试官轮流进来房间面试,一个面试官问半小时。问的技术问题不多,主要问项目细节。其中一个面试官的一个问题用英语问,要求用英语回答并讨论。这个面试官告诉我好多面对项目的态度和看法,要发散思维,考虑用户体验。(最后一家面试以英特尔结束,算是完美结束了。反正我不留上海,不过就不过了)

  C++八股文(一)

  参考回答:

  在全局变量前加上关键字 static,全局变量就定义成一个全局静态变量。

  静态存储区,在整个程序运行期间一直存在。

  初始化:未经初始化的全局静态变量会被自动初始化为 0(自动对象的值是任意的,除非他被显式初始化);

  作用域:全局静态变量在声明他的文件之外是不可见的,准确地说是从定义之处开始,到文件结尾。

  在局部变量之前加上关键字 static,局部变量就成为一个局部静态变量。

  内存中的位置:静态存储区

  初始化:未经初始化的全局静态变量会被自动初始化为 0(自动对象的值是任意的,除非他被显式初始化);

  作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域结束。但是当局部静态变量离开作用域后,并没有销毁,而是仍然驻留在内存当中,只不过我们不能再对它进行访问,直到该函数再次被调用,并且值不变;

  在函数返回类型前加 static,函数就定义为静态函数。函数的定义和声明在默认情况下都是 extern 的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。

  函数的实现使用 static 修饰,那么这个函数只可在本 cpp 内使用,不会同其他 cpp 中的同名函数引起冲突;

  warning:不要再头文件中声明 static 的全局函数,不要在 cpp 内声明非static 的全局函数,如果你要在多个 cpp 中复用该函数,就把它的声明提到头文件里去,否则 cpp 内部声明需加上 static 修饰;

  在类中,静态成员可以实现多个对象之间的数据共享,并且使用静态数据成员还不会破坏隐藏的原则,即保证了安全性。因此,静态成员是类的所有对象中共享的成员,而不是某个对象的成员。对多个对象来说,静态数据成员只存储一处,供所有对象共用

  静态成员函数和静态数据成员一样,它们都属于类的静态成员,它们都不是对象成员。因此,对静态成员的引用不需要用对象名。

  在静态成员函数的实现中不能直接引用类中说明的非静态成员,可以引用类中说明的静态成员(这点非常重要)。如果静态成员函数中要引用非静态成员时,可通过对象来引用。从中可看出,调用静态成员函数使用如下格式:;

  参考回答:

  C++ 是面向对象的语言,而C是面向过程的结构化编程语言

  C++ 具有封装、继承和多态三种特性C++ 相比 C,增加多许多类型安全的功能,比如强制类型转换、C++ 支持范式编程,比如模板类、函数模板等参考回答: C++ 中四种类型转换是:, ,,

  用于将 const 变量转为非 const

  用于各种隐式转换,比如非 const 转 const,void* 转指针等, static_cast能用于多态向上转化,如果向下转能成功但是不安全,结果未知;

  用于动态类型转换。只能用于含有虚函数的类,用于类层次间的向上和向下转化。只能转指针或引用。向下转化时,如果是非法的对于指针返回NULL,对于引用抛异常。要深入了解内部转换的原理。

  向上转换:指的是子类向基类的转换向下转换:指的是基类向子类的转换它通过判断在执行到该语句的时候变量的运行时类型和要转换的类型是否相同来判断是否能够进行向下转换。

  几乎什么都可以转,比如将int转指针,可能会出问题,尽量少用;

  C 的强制转换表面上看起来功能强大什么都能转,但是转化不够明确,不能进行错误检查,容易出错。

  参考回答

  指针有自己的一块空间,而引用只是一个别名;使用 sizeof 看一个指针的大小是4,而引用则是被引用对象的大小;指针可以被初始化为 NULL,而引用必须被初始化且必须是一个已有对象 的引用;作为参数传递时,指针需要被解引用才可以对对象进行操作,而直接对引 用的修改都会改变引用所指向的对象;可以有 const 指针,但是没有 const 引用;指针在使用中可以指向其它对象,但是引用只能是一个对象的引用,不能 被改变;指针可以有多级指针(**p),而引用止于一级;指针和引用使用++运算符的意义不一样;如果返回动态内存分配的对象或者内存,必须使用指针,引用可能引起内存泄露。参考回答:

  根据面积法,如果 P 在三角形 ABC 内,那么三角形 ABP 的面积+三角形 BCP 的面积+三角形 ACP 的面积应该等于三角形 ABC 的面积。算法如下:

  参考回答:

  判断一个数是不是二的倍数,即判断该数二进制末位是不是 0: 或者。求一个数中 1 的位数,可以直接逐位除十取余判断:参考回答:

  野指针就是指向一个已删除的对象或者未申请访问受限内存区域的指针

  参考回答:

  智能指针主要用于管理在堆上分配的内存,它将普通的指针封装为一个栈对象。当栈对象的生存周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄漏。C++ 11 中最常用的智能指针类型为 shared_ptr,它采用引用计数的方法,记录当前内存资源被多少个智能指针引用。该引用计数的内存在堆上分配。当新增一个时引用计数加1,当过期时引用计数减一。只有引用计数为 0 时,智能指针才会自动释放引用的内存资源。对 shared_ptr 进行初始化时不能将一个普通指针直接赋值给智能指针,因为一个是指针,一个是类。可以通过 make_shared 函数或者通过构造函数传入普通指针。并可以通过 get 函数获得普通指针。

  参考回答:

  当两个对象相互使用一个 shared_ptr 成员变量指向对方,会造成循环引用,使引用计数失效,从而导致内存泄漏。例如:

  参考回答:

  为了解决循环引用导致的内存泄漏,引入了 weak_ptr 弱指针,weak_ptr 的构造函数不会修改引用计数的值,从而不会对对象的内存进行管理,其类似一个普通指针,但不指向引用计数的共享内存,但是其可以检测到所管理的对象是否已经被释放,从而避免非法访问。

  参考回答:

  将可能会被继承的父类的析构函数设置为虚函数,可以保证当我们new一个子类,然后使用基类指针指向该子类对象,释放基类指针时可以释放掉子类的空间,防止内存泄漏。

  C++ 默认的析构函数不是虚函数是因为虚函数需要额外的虚函数表和虚表指针,占用额外的内存。而对于不会被继承的类来说,其析构函数如果是虚函数,就会浪费内存。因此 C++ 默认的析构函数不是虚函数,而是只有当需要当作父类时,设置为虚函数。

  参考文章《函数指针》

  参考回答:

  析构函数与构造函数对应,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统会自动执行析构函数。

  析构函数名也应与类名相同,只是在函数名前面加一个位取反符~,例如 ~stud( ),以区别于构造函数。它不能带任何参数,也没有返回值(包括 void 类型)。只能有一个析构函数,不能重载。

  如果用户没有编写析构函数,编译系统会自动生成一个缺省的析构函数(即使自定义了析构函数,编译器也总是会为我们合成一个析构函数,并且如果自定义了析构函数,编译器在执行时会先调用自定义的析构函数再调用合成的析构函数),它也不进行任何操作。所以许多简单的类中没有用显式的析构函数。

  如果一个类中有指针,且在使用的过程中动态的申请了内存,那么最好显示构造析构函数在销毁类之前,释放掉申请的内存空间,避免内存泄漏。

  类析构顺序:

  派生类本身的析构函数;对象成员析构函数;基类析构函数。参考回答:

  静态函数在编译的时候就已经确定运行时机,虚函数在运行的时候动态绑定。虚函数因为用了虚函数表机制,调用的时候会增加一次内存开销

  参考回答:

  重载:两个函数名相同,但是参数列表不同(个数,类型),返回值类型没有要求,在同一作用域中

  重写:子类继承了父类,父类中的函数是虚函数,在子类中重新定义了这个虚函数,这种情况是重写

  参考回答:

  strcpy 是字符串拷贝函数,原型:

  从 src 逐字节拷贝到 dest,直到遇到 '\0' 结束,因为没有指定长度,可能会导致拷贝越界,造成缓冲区溢出漏洞,安全版本是 strncpy 函数。

  strlen 函数是计算字符串长度的函数,返回从开始到 '\0' 之间的字符个数。

  参考回答:

  多态的实现主要分为静态多态和动态多态,静态多态主要是重载,在编译的时候就已经确定;动态多态是用虚函数机制实现的,在运行期间动态绑定。举个例子:一个父类类型的指针指向一个子类对象时候,使用父类的指针去调用子类中重写了的父类中的虚函数的时候,会调用子类重写过后的函数,在父类中声明为加了 virtual 关键字的函数,在子类中重写时候不需要加 virtual 也是虚函数。

  虚函数的实现:在有虚函数的类中,类的最开始部分是一个虚函数表的指针,这个指针指向一个虚函数表,表中放了虚函数的地址,实际的虚函数在代码段(.text)中。当子类继承了父类的时候也会继承其虚函数表,当子类重写父类中虚函数时候,会将其继承到的虚函数表中的地址替换为重新写的函数地址。使用了虚函数,会增加访问内存开销,降低效率。

  参考回答:

  ++i 先自增 1,再返回,i++ 先返回 i,再自增 1

  参考文章《为什么说++i比i++效率高》

  参考回答:

  参考回答:

  参考回答:

  常量在 C++ 里的定义就是一个 top-level const 加上对象类型,常量定义必须初始化。对于局部对象,常量存放在栈区,对于全局对象,常量存放在全局/静态存储区。对于字面值常量,常量存放在常量存储区。

  参考回答:

  const 修饰的成员函数表明函数调用不会对对象做出任何更改,事实上,如果确认不会对对象做更改,就应该为函数加上 const 限定,这样无论 const 对象还是普通对象都可以调用该函数。

  参考回答:

  不会,这相当于函数的重载。

  参考回答:

  首先,对于内置类型,低精度的变量给高精度变量赋值会发生隐式类型转换,其次,对于只存在单个参数的构造函数的对象构造来说,函数调用可以直接使用该参数传入,编译器会自动调用其构造函数生成临时对象。

  参考回答:

  默认是 1M,不过可以调整

  参考文章《C++是如何调用C接口的》

  参考回答:

  首先,new/delete 是 C++ 的关键字,而 malloc/free 是 C语言的库函数,后者使用必须指明申请内存空间的大小,对于类类型的对象,后者不会调用构造函数和析构函数

  参考回答:

  运行时类型检查,在 C++ 层面主要体现在 dynamic_cast 和typeid,VS 中虚函数表的 -1 位置存放了指向 type_info 的指针。对于存在虚函数的类型,typeid 和 dynamic_cast 都会去查询 type_info

  参考回答:

  子类若重写父类虚函数,虚函数表中,该函数的地址会被替换,对于存在虚函数的类的对象,在 VS 中,对象的对象模型的头部存放指向虚函数表的指针,通过该机制实现多态。

  参考回答:

  每一个函数调用都会分配函数栈,在栈内进行函数执行过程。调用前,先把返回地址压栈,然后把当前函数的 esp 指针压栈。

  参考文章《变长参数探究》

  参考回答:

  生成一个临时变量,把它的引用作为函数参数传入函数内。

  参考回答:

  不能。如果是这种情况下,调用拷贝构造函数的时候,首先要将实参传递给形参,这个传递的时候又要调用拷贝构造函数。。如此循环,无法完成拷贝,栈也会满。

  参考回答:

  select 在使用前,先将需要监控的描述符对应的 bit 位置 1,然后将其传给 select,当有任何一个事件发生时,select 将会返回所有的描述符,需要在应用程序自己遍历去检查哪个描述符上有事件发生,效率很低,并且其不断在内核态和用户态进行描述符的拷贝,开销很大

  参考回答:

  父进程产生子进程使用 fork 拷贝出来一个父进程的副本,此时只拷贝了父进程的页表,两个进程都读同一块内存,当有进程写的时候使用写实拷贝机制分配内存,exec 函数可以加载一个 elf 文件去替换父进程,从此父进程和子进程就可以运行不同的程序了。fork 从父进程返回子进程的 pid,从子进程返回 0.调用了 wait 的父进程将会发生阻塞,直到有子进程状态改变,执行成功返回 0,错误返回 -1。exec 执行成功则子进程从新的程序开始运行,无返回值,执行失败返回 -1

  参考回答:

  静态函数在编译的时候就已经确定运行时机,虚函数在运行的时候动态绑定。虚函数因为用了虚函数表机制,调用的时候会增加一次内存开销

  参考回答:

  重载:两个函数名相同,但是参数列表不同(个数,类型),返回值类型没有要求,在同一作用域中重写:子类继承了父类,父类中的函数是虚函数,在子类中重新定义了这个虚函数,这种情况是重写参考回答:

  map 和 set 都是 C++ 的关联容器,其底层实现都是红黑树(RB-Tree)。由于 map 和 set 所开放的各种操作接口,RB-tree 也都提供了,所以几乎所有的 map 和set的操作行为,都只是转调 RB-tree 的操作行为。

  map 和 set 区别在于:

  map 中的元素是 key-value(关键字—值)对:关键字起到索引的作用,值则表示与索引相关联的数据;Set 与之相对就是关键字的简单集合,set 中每个元素只包含一个关键字。 set 的迭代器是 const 的,不允许修改元素的值;map 允许修改 value,但不允许修改 key。其原因是因为 map 和 set 是根据关键字排序来保证其有序性的,如果允许修改 key 的话,那么首先需要删除该键,然后调节平衡,再插入修改后的键值,调节平衡,如此一来,严重破坏了 map 和 set 的结构,导致 iterator 失效,不知道应该指向改变前的位置,还是指向改变后的位置。所以 STL 中将 set 的迭代器设置成 const,不允许修改迭代器的值;而 map 的迭代器则不允许修改 key 值,允许修改 value 值。 map 支持下标操作,set 不支持下标操作。map 可以用 key 做下标,map 的下标运算符[ ]将关键码作为下标去执行查找,如果关键码不存在,则插入一个具有该关键码和 mapped_type 类型默认值的元素至 map 中,因此下标运算符[ ]在 map 应用中需要慎用,const_map 不能用,只希望确定某一个关键值是否存在而不希望插入元素时也不应该使用,mapped_type 类型没有默认值也不应该使用。如果 find 能解决需要,尽可能用 find。 参考回答:

  STL 的分配器用于封装 STL 容器在内存管理上的底层细节。在 C++ 中,其内存配置和释放如下:

  new 运算分两个阶段:调用 配置内存;调用对象构造函数构造对象内容delete 运算分两个阶段:调用对象希构函数;掉员工释放内存为了精密分工, 将两个阶段操作区分开来:内存配置有负责,内存释放由负责;对象构造由负责,对象析构由负责。

  同时为了提升内存管理的效率,减少申请小内存造成的内存碎片问题,SGI STL 采用了两级配置器,当分配的空间大小超过 128B 时,会使用第一级空间配置器;当分配的空间大小小于 128B 时,将使用第二级空间配置器。第一级空间配置器直接使用函数进行内存空间的分配和释放,而第二级空间配置器采用了内存池技术,通过空闲链表来管理内存。

  参考回答:

  这个主要考察的是迭代器失效的问题。

  对于序列容器来说,使用后,后边的每个元素的迭代器都会失效,但是后边每个元素都会往前移动一个位置,但是会返回下一个有效的迭代器;对于关联容器来说,使用了后,当前元素的迭代器失效,但是其结构是红黑树,删除当前元素的,不会影响到下一个元素的迭代器,所以在调用之前,记录下一个元素的迭代器即可。对于来说,它使用了不连续分配的内存,并且它的方法也会返回下一个有效的,因此上面两种正确的方法都可以使用。参考回答: 红黑树。底层结构是哈希表

  参考回答:

  STL 主要由:以下几部分组成:

  容器迭代器仿函数算法分配器配接器

  他们之间的关系:分配器给容器分配存储空间,算法通过迭代器获取容器中的内容,仿函数可以协助算法完成各种操作,配接器用来套接适配仿函数

  参考回答:

  Map映射,map 的所有元素都是 pair,同时拥有实值(value)和键值(key)。pair 的第一元素被视为键值,第二元素被视为实值。所有元素都会根据元素的键值自动被排序。不允许键值重复。底层实现:红黑树

  适用场景:有序键值对不重复映射

  Multimap 多重映射。 的所有元素都是 ,同时拥有实值()和键值()。 的第一元素被视为键值,第二元素被视为实值。所有元素都会根据元素的键值自动被排序。允许键值重复。底层实现:红黑树

  适用场景:有序键值对可重复映射

  Vector 连续存储的容器,动态数组,在堆上分配空间底层实现:数组

  两倍容量增长:

  增加(插入)新元素时,如果未超过当时的容量,则还有剩余空间,那么直接添加到最后(插入指定位置),然后调整迭代器。 如果没有剩余空间了,则会重新配置原有元素个数的两倍空间,然后将原空间元素通过复制的方式初始化新空间,再向新空间增加元素,最后析构并释放原空间,之前的迭代器会失效。

  性能:

  访问:O(1)

  插入:在最后插入(空间够):很快

  在最后插入(空间不够):需要内存申请和释放,以及对之前数据进行拷贝。在中间插入(空间够):内存拷贝在中间插入(空间不够):需要内存申请和释放,以及对之前数据进行拷贝。 删除:在最后删除:很快在中间删除:内存拷贝适用场景:经常随机访问,且不经常对非尾节点进行插入删除。 2. List 动态链表,在堆上分配空间,每插入一个元数都会分配空间,每删除一个元素都会释放空间。

  底层:双向链表

  性能:

  访问:随机访问性能很差,只能快速访问头尾节点。

  插入:很快,一般是常数开销

  删除:很快,一般是常数开销

  适用场景:经常插入删除大量数据

  区别:

  vector 底层实现是数组;list 是双向 链表。vector 支持随机访问,list 不支持。vector 是顺序内存,list 不是。vector 在中间节点进行插入删除会导致内存拷贝,list 不会。vector 一次性分配好内存,不够时才进行 2 倍扩容;list 每次插入新节点都会进行内存申请。vector 随机访问性能好,插入删除性能差;list 随机访问性能差,插入删除性能好。 应用 vector 拥有一段连续的内存空间,因此支持随机访问,如果需要高效的随即访问,而不在乎插入和删除的效率,使用 vector。list 拥有一段不连续的内存空间,如果需要高效的插入和删除,而不关心随机访问,则应使用 list。

  参考回答:

  迭代器Iterator(迭代器)模式又称 Cursor(游标)模式,用于提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。或者这样说可能更容易理解:Iterator 模式是运用于聚合对象的一种模式,通过运用该模式,使得我们可以在不知道对象内部表示的情况下,按照一定顺序(由 iterator 提供的方法)访问聚合对象中的各个元素。

  由于 Iterator 模式的以上特性:与聚合对象耦合,在一定程度上限制了它的广泛运用,一般仅用于底层聚合支持类,如 STL 的 list、vector、stack 等容器类及 ostream_iterator 等扩展 iterator。

  迭代器和指针的区别迭代器不是指针,是类模板,表现的像指针。他只是模拟了指针的一些功能,通过重载了指针的一些操作符,等。迭代器封装了指针,是一个“可遍历容器内全部或部分元素”的对象, 本质是封装了原生指针,是指针概念的一种提升(lift),提供了比指针更高级的行为,相当于一种智能指针,他可以根据不同类型的数据结构来实现不同的 ++,--等操作。

  迭代器返回的是对象引用而不是对象的值,所以 cout 只能输出迭代器使用 * 取值后的值而不能直接输出其自身。

  迭代器产生原因Iterator 类的访问方式就是把不同集合类的访问逻辑抽象出来,使得不用暴露集合内部的结构而达到循环遍历集合的效果。

  参考回答:

  调用顺序:

  首先创建一个 epoll 对象,然后使用 epoll_ctl 对这个对象进行操作,把需要监控的描述添加进去,这些描述如将会以 epoll_event 结构体的形式组成一颗红黑树,接着阻塞在 epoll_wait,进入大循环,当某个 fd 上有事件发生时,内核将会把其对应的结构体放入到一个链表中,返回有事件发生的链表。

  参考回答:

  参考回答:

  resize():改变当前容器内含有元素的数量(size()),eg: vectorv; v.resize(len);v的size变为len,如果原来v的size小于len,那么容器新增(len-size)个元素,元素的值为默认为0.当v.push_back(3);之后,则是3是放在了v的末尾,即下标为len,此时容器是size为len+1;

  reserve():改变当前容器的最大容量(capacity),它不会生成元素,只是确定这个容器允许放入多少对象,如果reserve(len)的值大于当前的capacity(),那么会重新分配一块能存len个对象的空间,然后把之前v.size()个对象通过copy construtor复制过来,销毁之前的内存;

  测试代码如下:

  参考回答:

  C++ 通过 public、protected、private 三个关键字来控制成员变量和成员函数的访问权限,它们分别表示公有的、受保护的、私有的,被称为成员访问限定符。在类的内部(定义类的代码内部),无论成员被声明为 public、protected 还是 private,都是可以互相访问的,没有访问权限的限制。在类的外部(定义类的代码之外),只能通过对象访问成员,并且通过对象只能访问 public 属性的成员,不能访问 private、protected 属性的成员

  参考回答:

  在 C++ 中,可以用 struct 和 class 定义类,都可以继承。区别在于:structural 的默认继承权限和默认访问权限是 public,而 class 的默认继承权限和默认访问权限是 private。 另外,class 还可以定义模板类形参,比如 template。

  参考回答:

  可以,必须通过成员函数初始化列表初始化。

  参考回答:

  Malloc 函数用于动态分配内存。为了减少内存碎片和系统调用的开销,malloc 其采用内存池的方式,先申请大块内存作为堆区,然后将堆区分为多个内存块,以块作为内存管理的基本单位。当用户申请内存时,直接从堆区分配一块合适的空闲块。 Malloc 采用隐式链表结构将堆区分成连续的、大小不一的块,包含已分配块和未分配块;同时 malloc 采用显示链表结构来管理所有的空闲块,即使用一个双向链表将空闲块连接起来,每一个空闲块记录了一个连续的、未分配的地址。

  当进行内存分配时,Malloc 会通过隐式链表遍历所有的空闲块,选择满足要求的块进行分配;当进行内存合并时,malloc 采用边界标记法,根据每个块的前后块是否已经分配来决定是否进行块合并。

  Malloc 在申请内存时,一般会通过 brk 或者 mmap 系统调用进行申请。其中当申请内存小于 128K 时,会使用系统函数 brk 在堆区中分配;而当申请内存大于 128K 时,会使用系统函数 mmap 在映射区分配。

  参考回答:

  在 C++ 中,虚拟内存分为代码段、数据段、BSS段、堆区、文件映射区以及栈区六部分。

  代码段:包括只读存储区和文本区,其中只读存储区存储字符串常量,文本区存储程序的机器代码。数据段:存储程序中已初始化的全局变量和静态变量bss 段:存储未初始化的全局变量和静态变量(局部+全局),以及所有被初始化为0的全局变量和静态变量。堆区:调用new/malloc函数时在堆区动态分配内存,同时需要调用delete/free来手动释放申请的内存。映射区:存储动态链接库以及调用mmap函数进行的文件映射栈:使用栈空间存储函数的返回地址、参数、局部变量、返回值参考回答:

  32bitCPU 可寻址 4G 线性空间,每个进程都有各自独立的 4G 逻辑地址,其中 0~3G 是用户态空间,3~4G 是内核空间,不同进程相同的逻辑地址会映射到不同的物理地址中。其逻辑地址其划分如下:

  各个段说明如下:

  3G 用户空间和 1G 内核空间

  静态区域:

  text segment(代码段):包括只读存储区和文本区,其中只读存储区存储字符串常量,文本区存储程序的机器代码。 data segment(数据段):存储程序中已初始化的全局变量和静态变量 bss segment:存储未初始化的全局变量和静态变量(局部+全局),以及所有被初始化为0的全局变量和静态变量,对于未初始化的全局变量和静态变量,程序运行main之前时会统一清零。即未初始化的全局变量编译器会初始化为 0 动态区域: heap(堆):当进程未调用 malloc 时是没有堆段的,只有调用 malloc 时采用分配一个堆,并且在程序运行过程中可以动态增加堆大小(移动 break 指针),从低地址向高地址增长。分配小内存时使用该区域。 堆的起始地址由 mm_struct 结构体中的 start_brk 标识,结束地址由 brk 标识。 memory mapping segment(映射区):存储动态链接库等文件映射、申请大内存( malloc 时调用 mmap 函数) stack(栈):使用栈空间存储函数的返回地址、参数、局部变量、返回值,从高地址向低地址增长。在创建进程时会有一个最大栈大小,Linux 可以通过 ulimi t命令指定。 参考回答:

  内存泄漏通常是由于调用了 malloc/new 等内存申请的操作,但是缺少了对应的 free/delete。为了判断内存是否泄露,我们一方面可以使用 linux 环境下的内存泄漏检查工具 Valgrind,另一方面我们在写代码时可以添加内存申请和释放的统计功能,统计当前申请和释放的内存是否一致,以此来判断内存是否泄露。

  参考回答:

  段错误通常发生在访问非法内存地址的时候,具体来说分为以下几种情况:

  使用野指针试图修改字符串常量的内容参考回答:

  内存泄漏(memory leak)是指由于疏忽或错误造成了程序未能释放掉不再使用的内存的情况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。

  内存泄漏的分类:

  堆内存泄漏 (Heap leak)。对内存指的是程序运行中根据需要分配通过 malloc,realloc new 等从堆中分配的一块内存,再是完成后必须通过调用对应的 free或者delete 删掉。如果程序的设计的错误导致这部分内存没有被释放,那么此后这块内存将不会被使用,就会产生Heap Leak.系统资源泄露(Resource Leak)。主要指程序使用系统分配的资源比如 Bitmap,handle ,SOCKET 等没有使用相应的函数释放掉,导致系统资源的浪费,严重可导致系统效能降低,系统运行不稳定。没有将基类的析构函数定义为虚函数。当基类指针指向子类对象时,如果基类的析构函数不是 virtual,那么子类的析构函数将不会被调用,子类的资源没有正确是释放,因此造成内存泄露。参考回答:

  reactor 模型要求主线程只负责监听文件描述上是否有事件发生,有的话就立即将该事件通知工作线程,除此之外,主线程不做任何其他实质性的工作,读写数据、接受新的连接以及处理客户请求均在工作线程中完成。其模型组成如下:

  Handle:即操作系统中的句柄,是对资源在操作系统层面上的一种抽象,它可以是打开的文件、一个连接等。由于模式一般使用在网络编程中,因而这里一般指,即一个网络连接。(同步事件复用器):阻塞等待一系列的中的事件到来,如果阻塞等待返回,即表示在返回的 中可以不阻塞的执行返回的事件类型。这个模块一般使用操作系统的 来实现。:用于管理 ,即 的容器,用以注册、移除 EventHandler 等;另外,它还作为 Reactor 模式的入口调用 的 方法以阻塞等待事件返回,当阻塞等待返回时,根据事件发生的将其分发给对应的 处理,即回调 中的 方法。 4.:定义事件处理方法:,以供回调使用。:事件 接口,实现特定事件处理逻辑。参考回答:

  在单线程模型中,可以采用 I/O 复用来提高单线程处理多个请求的能力,然后再采用事件驱动模型,基于异步回调来处理事件来

  参考回答:

  IO 多路复用IO 复用模型在阻塞 IO 模型上多了一个 select 函数,select 函数有一个参数是文件描述符集合,意思就是对这些的文件描述符进行循环监听,当某个文件描述符就绪的时候,就对这个文件描述符进行处理。

  这种 IO 模型是属于阻塞的 IO。但是由于它可以对多个文件描述符进行阻塞监听,所以它的效率比阻塞 IO 模型高效。

  IO 多路复用就是我们说的的好处就在于单个 process 就可以同时处理多个网络连接的 IO。它的基本原理就是 这个 function 会不断的轮询所负责的所有 socket,当某个 socket 有数据到达了,就通知用户进程。

  当用户进程调用了 select,那么整个进程会被 block,而同时,kernel 会“监视”所有 select 负责的 socket,当任何一个 socket 中的数据准备好了,select 就会返回。这个时候用户进程再调用 read 操作,将数据从 kernel 拷贝到用户进程。

  所以,I/O 多路复用的特点是通过一种机制一个进程能同时等待多个文件描述符,而这些文件描述符(套接字描述符)其中的任意一个进入读就绪状态,select() 函数就可以返回。

  I/O 多路复用和阻塞I/O其实并没有太大的不同,事实上,还更差一些。因为这里需要使用两个,而只调用了一个。但是,用的优势在于它可以同时处理多个。

  所以,如果处理的连接数不是很高的话,使用的不一定比使用的性能更好,可能延迟还更大。的优势并不是对于单个连接能处理得更快,而是在于能处理更多的连接。)

  在中,实际中,对于每一个,一般都设置成为,但是,如上图所示,整个用户的其实是一直被的。只不过是被这个函数,而不是被给。

  2、select

  select:是最初解决 IO 阻塞问题的方法。用结构体 fd_set 来告诉内核监听多个文件描述符,该结构体被称为描述符集。由数组来维持哪些描述符被置位了。对结构体的操作封装在三个宏定义中。通过轮寻来查找是否有描述符要被处理。 存在的问题:

  内置数组的形式使得 select 的最大文件数受限与 FD_SIZE;每次调用 select 前都要重新初始化描述符集,将 fd 从用户态拷贝到内核态,每次调用 select 后,都需要将 fd 从内核态拷贝到用户态;轮寻排查当文件描述符个数很多时,效率很低;3、poll

  poll:通过一个可变长度的数组解决了select 文件描述符受限的问题。数组中元素是结构体,该结构体保存描述符的信息,每增加一个文件描述符就向数组中加入一个结构体,结构体只需要拷贝一次到内核态。poll 解决了 select 重复初始化的问题。轮寻排查的问题未解决。

  4、epoll

  epoll:轮寻排查所有文件描述符的效率不高,使服务器并发能力受限。因此,epoll 采用只返回状态发生变化的文件描述符,便解决了轮寻的瓶颈。

  epoll 对文件描述符的操作有两种模式:和。LT 模式是默认模式

  LT模式

  是缺省的工作方式,并且同时支持 block 和 .在这种做法中,内核告诉你一个文件描述符是否就绪了,然后你可以对这个就绪的 fd 进行 IO 操作。如果你不作任何操作,内核还是会继续通知你的。

  ET模式

  是高速工作方式,只支持。在这种模式下,当描述符从未就绪变为就绪时,内核通过 epoll 告诉你。然后它会假设你知道文件描述符已经就绪,并且不会再为那个文件描述符发送更多的就绪通知,直到你做了某些操作导致那个文件描述符不再为就绪状态了(比如,你在发送,接收或者接收请求,或者发送接收的数据少于一定量时导致了一个 错误)。但是请注意,如果一直不对这个fd作IO操作(从而导致它再次变成未就绪),内核不会发送更多的通知(only once)

  ET 模式在很大程度上减少了 epoll 事件被重复触发的次数,因此效率要比LT模式高。epoll 工作在 ET 模式的时候,必须使用非阻塞套接口,以避免由于一个文件句柄的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死。

  3、LT 模式与 ET 模式的区别如下:

  LT 模式:当检测到描述符事件发生并将此事件通知应用程序,应用程序可以不立即处理该事件。下次调用时,会再次响应应用程序并通知此事件。

  ET 模式:当检测到描述符事件发生并将此事件通知应用程序,应用程序必须立即处理该事件。如果不处理,下次调用时,不会再次响应应用程序并通知此事件。

  参考回答:

  C++11 最常用的新特性如下:

  auto 关键字:编译器可以根据初始值自动推导出类型。但是不能用于函数传参以及数组类型的推导nullptr 关键字:nullptr 是一种特殊类型的字面值,它可以被转换成任意其它的指针类型;而 NULL 一般被宏定义为 0,在遇到重载时可能会出现问题。智能指针:C++11 新增了、等类型的智能指针,用于解决内存管理的问题。初始化列表:使用初始化列表来对类进行初始化右值引用:基于右值引用可以实现移动语义和完美转发,消除两个对象交互时不必要的对象拷贝,节省运算存储资源,提高效率atomic 原子操作用于多线程资源互斥操作新增 STL 容器 arra y以及 tuple

  看完这个视频就够了,其它的都不用看!

  最近指导了一位同学,他获得某公司的C++服务器开发岗的笔试机会。

  要求线上答题,是开放式答题,只要在规定时间内把题目做好提交即可。

  和我沟通指导后,很顺利的通过了笔试。现在把整个指导过程记录一下,以作分享。

  In this project, we want to create a cross reference generator. We assume that we have a file of text(GNU GENERAL PUBLIC LICENSE is a good candidate). We want to read in the file and print out an alphabetized list of all the words in the file, using the following format:

  You may assume that your cross-reference generator is not case-sensitive, that is the words “Did” and “did” are the same. And again you can use Pseudo Code (some sample pseudo code is on Page 4) or Lua if you can complete in time. At least explain your idea.

  For example, running the cross-reference generator with the first two lines from the poem

  Jabberwocky by Lewis Carroll produce the following:

  Line 1 Twas brillig and the slithy toves Line 2 Did gyre and gimble in the wabe

  以上就是全部问题。

  题目其实并不很难,技术经理出这个题目,大概是想考核两个“技术点”。

  第一点,就是怎样处理英文文档的项目需求。国内程序员,大部分的英语水平非常一般,如果能保持高中生的英语水平,已经算是程序员中的“佼佼者”了,但是对于程序员老鸟,这并不妨碍处理英文文档。直接使用网络工具,加项目理解,基本上就能理解了。推荐工具,使用有道词典。需要注意的是,翻译工具翻译后只能作为参考,需要程序员结合语境进行“二次翻译”。

  第二点,就是使用C++解决问题的能力。这个题目,难度并不大,但是如果对C++的各种基础容器不是很熟悉的话,直接使用C语言“裸写“,可能会导致时间上不够用,最后感叹这个题自己会做,只是出了点小问题,没有做完,没有做好。

  原文出处:奇牛编程Rock老师

  更多面试资源:传送门

  记得大概十年前,我在前前一家公司负责给我的组里面试几个应届生,一面,c/c++ windows app岗位。

  我到现在还蛮得意那次出的面试题。一场温馨的开卷考试~

  当时我的领导给了几个大概考核点:c/c++写代码能力、英文资料阅读能力、沟通能力,还有一些其他的,记不全了。

  我挑了几个windows上常见,但应届生大概率没怎么接触过的东西。其中之一是BMP图片文件格式读取。

  我先在MSDN上找了一大篇格式说明文档(英文,应领导要求),印象里大概打印了四、五张A4纸。

  然后我给出了一个目标内存格式。要求面试者在两个小时之内读懂、读全文档,并写个c/c++函数,读取任意类型的BMP文件,输出我指定的内存格式。用准确的c/c++代码写最好,部分伪码也行。(别看不起BMP文件,它有4/8位调色板彩色格式、15/16/24/32位直接彩色格式,还有RLE4/8两种游程压缩格式,也够折腾一阵的;我还准备一份TIFF的文档以备万一。)此外我还选了其他几个小技术,具体记不清了。

  期间我除了给端茶倒水之外,不进屋骚扰,不站在面试者身后招讨厌(个人极度讨厌这种)。给一打白纸,铅笔橡皮,不用白板。十年前那会儿笔记本电脑还没有人手一台,不然我更倾向于用电脑写。

  后来我领导出差去南方面试其他候选人,还借走了我的题。心里美滋滋。

  这里给大家分享一些常见C++面试.(由于篇幅有限,只展示首页部分截图,需要的戳下面链接)

  大厂15万字C++开发面试手册出炉(C++和计算机基础全有)目录如下:

  首页部分展示首页部分展示1)C是面向过程的语言,是一个结构化的语言,考虑如何通过一个过程对输入进行处理得到输出;C++是面向对象的语言,主要特征是“封装、继承和多态”。封装隐藏了实现细节,使得代码模块化;派生类可以继承父类的数据和方法,扩展了已经存在的模块,实现了代码重用;多态则是“一个接口,多种实现”,通过派生类重写父类的虚函数,实现了接口的重用。

  2)C和C++动态管理内存的方法不一样,C是使用malloc/free,而C++除此之外还有new/delete关键字。

  3)C++中有引用,C中不存在引用的概念

  1)指针是一个新的变量,存储了另一个变量的地址,我们可以通过访问这个地址来修改另一个变量;

  引用只是一个别名,还是变量本身,对引用的任何操作就是对变量本身进行操作,以达到修改变量的目的

  2)引用只有一级,而指针可以有多级

  3)指针传参的时候,还是值传递,指针本身的值不可以修改,需要通过解引用才能对指向的对象进行操作

  引用传参的时候,传进来的就是变量本身,因此变量可以被修改

  结构体:将不同类型的数据组合成一个整体,是自定义类型

  共同体:不同类型的几个变量共同占用一段内存

  1)结构体中的每个成员都有自己独立的地址,它们是同时存在的;

  共同体中的所有成员占用同一段内存,它们不能同时存在;

  2)sizeof(struct)是内存对齐后所有成员长度的总和,sizeof(union)是内存对齐后最长数据成员的长度、

  结构体为什么要内存对齐呢?

  1.平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据,某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常

  2.硬件原因:经过内存对齐之后,CPU的内存访问速度大大提升。

  华为最牛逼的c++ 基础与提高PDF侯捷C++全套视频|含下载方式

  1)#define定义的常量没有类型,所给出的是一个立即数;const定义的常量有类型名字,存放在静态区域

  2)处理阶段不同,#define定义的宏变量在预处理时进行替换,可能有多个拷贝,const所定义的变量在编译时确定其值,只有一个拷贝。

  3)#define定义的常量是不可以用指针去指向,const定义的常量可以用指针去指向该常量的地址

  4)#define可以定义简单的函数,const不可以定义函数

  1)overload,将语义相近的几个函数用同一个名字表示,但是参数列表(参数的类型,个数,顺序不同)不同,这就是函数重载,返回值类型可以不同

  特征:相同范围(同一个类中)、函数名字相同、参数不同、virtual关键字可有可无

  2)override,派生类覆盖基类的虚函数,实现接口的重用,返回值类型必须相同

  特征:不同范围(基类和派生类)、函数名字相同、参数相同、基类中必须有virtual关键字(必须是虚函数)

  3)overwrite,派生类屏蔽了其同名的基类函数,返回值类型可以不同

  特征:不同范围(基类和派生类)、函数名字相同、参数不同或者参数相同且无virtual关键字

  new/delete,malloc/free都是动态分配内存的方式

  1)malloc对开辟的空间大小严格指定,而new只需要对象名

  2)new为对象分配空间时,调用对象的构造函数,delete调用对象的析构函数

  既然有了malloc/free,C++中为什么还需要new/delete呢?

  运算符是语言自身的特性,有固定的语义,编译器知道意味着什么,由编译器解释语义,生成相应的代码。

  库函数是依赖于库的,一定程度上独立于语言的。编译器不关心库函数的作用,只保证编译,调用函数参数和返回值符合语法,生成call函数的代码。

  malloc/free是库函数,new/delete是C++运算符。对于非内部数据类型而言,光用malloc/free无法满足动态对象都要求。new/delete是运算符,编译器保证调用构造和析构函数对对象进行初始化/析构。但是库函数malloc/free是库函数,不会执行构造/析构。

  delete只会调用一次析构函数,而delete[]会调用每个成员的析构函数

  用new分配的内存用delete释放,用new[]分配的内存用delete[]释放

  一.构造函数

  构造函数是和类名相同的一个函数,它的作用是实现对象的初始化。当对象被创建时,构造函数自动被调用。

  特点:

  1.没有类型

  2.没有返回值(也不用写void)

  3.名字与类名相同

  4.可重载!

  作用:完成类的对象的初始化

  Cdate d; //定义对象d

  注意:当对象d被创建时,会自动调用构造函数 d.Cdate()。

  当类中未定义构造函数时,编译器会自动假设存在以下两个默认构造函数:(此构造函数什么都不做,就是个形式)。如果作者自己定义了构造函数,则默认的构造函数不会存在。

  //默认构造函数一

  Cdate::Cdate()

  {

  }

  //默认构造函数二

  Cdate::Cdate(const Cdate& a)

  {

  }

  三.析构函数

  我们已经知道构造函数是在创建对象时,对其进行初始化。而析构函数与其相反,是在对象被删除前象由系统自动执行它做清理工作。

  作为一个类,可能有多个对象,每个对象生命结束时都要调用析构函数,且每个对象调用一次。

  特点:

  1.无类型

  2.无返回值

  3.名字与类名相同

  4.不带参数,不可重载,析构函数只有一个!

  5.析构函数前“~” (取反符,表示逆构造函数)

  作用:在对象被删除前做清理工作。

  注意:对象的析构函数在对象被销毁前被调用,对象何时销毁也与其作用域相关。

  例如,全局对象是在程序运行结束时销毁;

  自动对象是在离开其作用域时销毁;

  而动态对象是在使用delete运算符时销毁。

  析构函数特别适用于当一个对象被动态分配内存空间,而在对象被销毁前希望释放它所占用的内存空间的时候。我们不会忽略初始化的重要性,却常常忽略清除的重要性,然而对销毁变量的内存清理是非常重要的。

  例如,我们在堆中申请了一些内存,如果没有用完就释放,会造成内存泄露,会导致应用程序运行效率降低,甚至崩溃,不可掉以轻心。

  而在c++中提供有析构函数,可以保证对象清除工作自动执行。

  析构与构造的调用次序相反,即最先构造的最后被析构,最后构造的最先被析构。

  虚函数:虚函数是C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数,是C++中多态性的一个重要体现。利用基类指针访问派生类中的虚函数,这种情况下采用的是动态绑定技术。

  纯虚函数:纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”.纯虚函数不能实例化对象。

  抽象类的介绍

  抽象类是一种特殊的类,它是为了抽象和设计的目的为建立的,它处于继承层次结构的较上层。

  (1)抽象类的定义: 称带有纯虚函数的类为抽象类。

  (2)抽象类的作用: 抽象类的主要作用是将有关的操作作为结果接口组织在一个继承层次结构中,由它来为派生类提供一个公共的根,派生类将具体实现在其基类中作为接口的操作。所以派生类实际上刻画了一组子类的操作接口的通用语义,这些语义也传给子类,子类可以具体实现这些语义,也可以再将这些语义传给自己的子类。

  (3)使用抽象类时注意:

  抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。如果派生类中没有重新定义纯虚函数,而只是继承基类的纯虚函数,则这个派生类仍然还是一个抽象类。如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类了,它是一个可以建立对象的具体的类。抽象类是不能定义对象的。

  总结:

  1、纯虚函数声明如下: virtual void funtion1()=0; 纯虚函数一定没有定义,纯虚函数用来规范派生类的行为,即接口。包含纯虚函数的类是抽象类,抽象类不能定义实例,但可以声明指向实现该抽象类的具体类的指针或引用。2、虚函数声明如下:virtual ReturnType FunctionName(Parameter) 虚函数必须实现,如果不实现,编译器将报错,错误提示为:3、对于虚函数来说,父类和子类都有各自的版本。由多态方式调用的时候动态绑定。4、实现了纯虚函数的子类,该纯虚函数在子类中就编程了虚函数,子类的子类即孙子类可以覆盖该虚函数,由多态方式调用的时候动态绑定。5、虚函数是C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数。6、在有动态分配堆上内存的时候,析构函数必须是虚函数,但没有必要是纯虚的。纯虚函数的引入,是出于两个目的:

  1、为了安全,因为避免任何需要明确但是因为不小心而导致的未知的结果,提醒子类去做应做的实现。2、为了效率,不是程序执行的效率,而是为了编码的效率。动态绑定:基类指针是调用派生类的中的成员函数还是调用基类中的成员函数要到程序运行时确定。主要看此时基类指针所指向的对象。这里要涉及一些很重要的概念,也是我最近看完Effective C++才明白的东西,记录下来。这些概念就是静态类型和动态类型,静态绑定和动态绑定。静态绑定和动态绑定。静态绑定是说前期绑定。所谓对象的静态类型,就是它在程序中被声明的时候采用的类型。考虑下面的class继承体系:

  class Shape{

  virtual void draw(color = Red) const=0;

  ...

  ...

  };

  class Rectangle:public Shape{

  virtual void draw(color = Red) const;

  ...

  ...

  };

  class Circle:public Shape

  {

  virtual void draw(color = Red) const;

  ...

  ...

  };

  现在考虑以下这些指针:

  Shape* ps;//静态类型为Shape*

  Shape*pc =new Circle;//静态类型Shape*

  Shape*pr = new Rectangle;//静态类型Shape*

  在本例中,ps,pc,pr都被声明为Shape*类型的,所以它们的静态类型都是Shape*。注意:无论它们真正指向什么,它们的静态类型都是Shape*.所谓的对象的动态类型是指“当前所指对象的类型”。也就是说,动态类型可以表现出一个对象将会有什么行为。根据上面的例子,pc的动态类型是Circle*,pr的动态类型是Rectangle*。ps没有动态类型,因为它没有指向任何对象。动态类型一如其名所示,可以在执行过程中改变(通常是经过赋值运算):

  ps=pc; \\ps的动态类型如今是Circle*

  ps=pr; \\ps的动态类型如今是Rectangle*

  Virtual函数系动态绑定而来,意思是调用一个virtual函数的时候,究竟调用的是哪一个函数代码,取决于发出调用的那个对象的动态类型。

  ps->draw(); \\调用的是Rectangle::draw(Red)

  推荐阅读书单

  正如侯捷老师所说C++ 相关的书籍也非常多,如天上繁星。 广博如四库全书者有 《The C++Programming Language》 《C++ Primer》,深奥如山重水复者有《The Annotated C++ Reference Manual》、《Inside The C++ Object Model》,细说历史者有《The Design And Evolution Of C++》、《Rumiations on C++》,独沽一味者有《Polymorphism in C++》、《Genericity in C++》,独树一帜者有《Design Patterns》、《C++ FAQs》,程序库大全有之《The C++ Standard Library》.....

  至于书单的话,可以看下这个C++ 最全书单,包含几十本经典的PDF和下载方式:

  华为最牛逼的c++ 基础与提高PDF?mp.weixin.qq.com/s?__biz=MzU4MjgwNjQ0OQ==&mid=2247486995&idx=1&sn=382ef6a0c1d20bdcc4531463024a8060&chksm=fdb3f0cdcac479dbf38c2db05f3d57ef6cb2acbd2edf977244523026a58258520a784933810b#rd?mp.weixin.qq.com/s?__biz=MzU4MjgwNjQ0OQ==&mid=2247486995&idx=1&sn=382ef6a0c1d20bdcc4531463024a8060&chksm=fdb3f0cdcac479dbf38c2db05f3d57ef6cb2acbd2edf977244523026a58258520a784933810b#rd?mp.weixin.qq.com/s?__biz=MzU4MjgwNjQ0OQ==&mid=2247486995&idx=1&sn=382ef6a0c1d20bdcc4531463024a8060&chksm=fdb3f0cdcac479dbf38c2db05f3d57ef6cb2acbd2edf977244523026a58258520a784933810b#rd(PS:侯捷 C++ 视频课程一直都被看过的同学广为推荐,最近发现 B 站关于侯捷老师的 C++ 视频课程几乎全部被下架了,于是自己搜集了一套非常全的视频,大家赶紧去下载保存备用:

  侯捷C++全套视频|含下载方式?mp.weixin.qq.com/s?__biz=MzU4MjgwNjQ0OQ==&mid=2247486987&idx=1&sn=6002f1b0c275f97a33ee2e3e8f53ab4f&chksm=fdb3f0d5cac479c3368acf8cecbf5b0669ff76db88b3f32d3543fcd8f0f5c820845102493c16#rd?mp.weixin.qq.com/s?__biz=MzU4MjgwNjQ0OQ==&mid=2247486987&idx=1&sn=6002f1b0c275f97a33ee2e3e8f53ab4f&chksm=fdb3f0d5cac479c3368acf8cecbf5b0669ff76db88b3f32d3543fcd8f0f5c820845102493c16#rd?mp.weixin.qq.com/s?__biz=MzU4MjgwNjQ0OQ==&mid=2247486987&idx=1&sn=6002f1b0c275f97a33ee2e3e8f53ab4f&chksm=fdb3f0d5cac479c3368acf8cecbf5b0669ff76db88b3f32d3543fcd8f0f5c820845102493c16#rd他们让知识的传播变得更加的便捷,降低了后来者的学习门槛,当然啦也变相加重了内卷化.

  STL包括两部分内容:容器和算法

  容器即存放数据的地方,比如array, vector,分为两类,序列式容器和关联式容器

  序列式容器,其中的元素不一定有序,但是都可以被排序,比如vector,list,queue,stack,heap, priority-queue, slist

  关联式容器,内部结构是一个平衡二叉树,每个元素都有一个键值和一个实值,比如map, set, hashtable, hash_set

  算法有排序,复制等,以及各个容器特定的算法

  迭代器是STL的精髓,迭代器提供了一种方法,使得它能够按照顺序访问某个容器所含的各个元素,但无需暴露该容器的内部结构,它将容器和算法分开,让二者独立设计。

  Vector是顺序容器,是一个动态数组,支持随机存取、插入、删除、查找等操作,在内存中是一块连续的空间。在原有空间不够情况下自动分配空间,增加为原来的两倍。vector随机存取效率高,但是在vector插入元素,需要移动的数目多,效率低下。

  注意:vector动态增加大小时,并不是在原空间之后持续新空间(因为无法保证原空间之后尚有可供配置的空间),而是以原大小的两倍另外配置一块较大的空间,然后将原内容拷贝过来,然后才开始在原内容之后构造新元素,并释放原空间。因此,对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了。

  

   上一篇:CPA复习备考丨跟着驴酱60天速通会计
下一篇:事关“小升初”!信都教育特别提醒...

最近更新未来教育