logo资料库

C++面试题集锦.pdf

第1页 / 共140页
第2页 / 共140页
第3页 / 共140页
第4页 / 共140页
第5页 / 共140页
第6页 / 共140页
第7页 / 共140页
第8页 / 共140页
资料共140页,剩余部分请下载后查看
I.C++
1.引用和指针的区别?
2.从汇编层去解释一下引用
3.C++中的指针参数传递和引用参数传递
4.形参与实参的区别?
5.static的用法和作用?
6.静态变量什么时候初始化
7. const?
8.const成员函数的理解和应用?
9.指针和const的用法
10.mutable
11.extern用法?
12.int转字符串字符串转int?strcat,strcpy,strncpy,memset,memcpy
13.深拷贝与浅拷贝?
14.C++模板是什么,底层怎么实现的?
15.C语言struct和C++struct区别
16.虚函数可以声明为inline吗?
17.类成员初始化方式?构造函数的执行顺序 ?为什么用成员初始化列表会快一些?
18.成员列表初始化?
19.构造函数为什么不能为虚函数?析构函数为什么要虚函数?
20.析构函数的作用,如何起作用?
21.构造函数和析构函数可以调用虚函数吗,为什么
22.构造函数的执行顺序?析构函数的执行顺序?构造函数内部干了啥?拷贝构造干了啥?
23.虚析构函数的作用,父类的析构函数是否要设置为虚函数?
24.构造函数析构函数可以调用虚函数吗?
25.构造函数析构函数可否抛出异常
26.类如何实现只能静态分配和只能动态分配
27.如果想将某个类用作基类,为什么该类必须定义而非声明?
28.什么情况会自动生成默认构造函数?
29.什么是类的继承?
30.什么是组合?
31.抽象基类为什么不能创建对象?
32.类什么时候会析构?
33.为什么友元函数必须在类内部声明?
34.介绍一下C++里面的多态?
35. 用C语言实现C++的继承
36.继承机制中对象之间如何转换?指针和引用之间如何转换?
37.组合与继承优缺点?
38.左值右值
39.移动构造函数
40.C语言的编译链接过程?
41.vector与list的区别与应用?怎么找某vector或者list的倒数第二个元素
42.STL vector的实现,删除其中的元素,迭代器如何变化?为什么是两倍扩容?释放空间?
43.容器内部删除一个元素
44.STL迭代器如何实现
45.set与hash_set的区别
46.hashmap与map的区别
47.map、set是怎么实现的,红黑树是怎么能够同时实现这两种容器? 为什么使用红黑树?
48.如何在共享内存上使用stl标准库?
49.map插入方式有几种?
50.STL中unordered_map(hash_map)和map的区别,hash_map如何解决冲突以
51.vector越界访问下标,map越界访问下标?vector删除元素时会不会释放空间?
52.map[]与find的区别?
53.STL中list与queue之间的区别
54.STL中的allocator,deallocator
55.STL中hash_map扩容发生什么? 
56.map如何创建?
57.vector的增加删除都是怎么做的?为什么是1.5倍?
58.函数指针?
59.说说你对c和c++的看法,c和c++的区别?
60.c/c++的内存分配,详细说一下栈、堆、静态存储区?
61.堆与栈的区别?
62.野指针是什么?如何检测内存泄漏?
63.悬空指针和野指针有什么区别?
64.内存泄漏
65.new和malloc的区别?
66.delete p;与delete[]p,allocator
67.new和delete的实现原理, delete是如何知道释放内存的大小的额?
68.malloc申请的存储空间能用delete释放吗
69.malloc与free的实现原理?
70.malloc、realloc、calloc的区别
71.__stdcall和__cdecl的区别?
72.使用智能指针管理内存资源,RAII
73.手写实现智能指针类
74.内存对齐?位域?
75.结构体变量比较是否相等
76.位运算
77.为什么内存对齐
78.函数调用过程栈的变化,返回值和参数变量哪个先入栈?
79.怎样判断两个浮点数是否相等?
80.宏定义一个取两个数中较大值的功能
81.define、const、typedef、inline使用方法?
82.printf实现原理?
83.#include 的顺序以及尖叫括号和双引号的区别
84.lambda函数
85. hello world 程序开始到打印到屏幕上的全过程?
86.模板类和模板函数的区别是什么?
87.为什么模板类一般都是放在一个h文件中
88.C++中类成员的访问权限和继承权限问题。
89.cout和printf有什么区别?
90.重载运算符?
91.函数重载函数匹配原则
92.定义和声明的区别
93.C++类型转换有四种
94.全局变量和static变量的区别
95.静态成员与普通成员的区别
96.说一下理解 ifdef  endif
97.隐式转换,如何消除隐式转换?
98.虚函数的内存结构,那菱形继承的虚函数内存结构呢
99.多继承的优缺点,作为一个开发者怎么看待多继承
100.迭代器++it,it++哪个好,为什么
101.C++如何处理多个异常的?
102.模板和实现可不可以不写在一个文件里面?为什么?
103.在成员函数中调用delete this会出现什么问题?对象还可以使用吗?
104.智能指针的作用;
105.auto_ptr作用
106.class、union、struct的区别
107.动态联编与静态联编
108.动态编译与静态编译
109.动态链接和静态链接区别
110.在不使用额外空间的情况下,交换两个数?
111.strcpy和memcpy的区别
112.执行int main(int argc, char *argv[])时的内存结构
113.volatile关键字的作用?
114.讲讲大端小端,如何检测(三种方法)
115.查看内存的方法
116.空类会默认添加哪些东西?怎么写?
117.标准库是什么?
118.const char* 与string之间的关系,传递参数问题?
119.new、delete、operator new、operator delete、placement
120.为什么拷贝构造函数必须传引用不能传值?
121.空类的大小是多少?为什么?
122.你什么情况用指针当参数,什么时候用引用,为什么?
123.大内存申请时候选用哪种?C++变量存在哪?变量的大小存在哪?符号表存在哪?
124.为什么会有大端小端,htol这一类函数的作用
125.静态函数能定义为虚函数吗?常函数?
126.this指针调用成员变量时,堆栈会发生什么变化?
127.静态绑定和动态绑定的介绍
128.设计一个类计算子类的个数
129.怎么快速定位错误出现的地方
130.虚函数的代价?
131.类对象的大小
132.移动构造函数
133.何时需要合成构造函数
134.何时需要合成复制构造函数
135.何时需要成员初始化列表?过程是什么?
136.程序员定义的析构函数被扩展的过程?
137.构造函数的执行算法?
138.构造函数的扩展过程?
139.哪些函数不能是虚函数
140.sizeof 和strlen 的区别
141.简述strcpy、sprintf与memcpy的区别
142.编码实现某一变量某位清0或置1
143.将“引用”作为函数参数有哪些特点?
144.分别写出BOOL,int,float,指针类型的变量a 与“零”的比较语句。
145.局部变量全局变量的问题?
146.数组和指针的区别?
147.C++如何阻止一个类被实例化?一般在什么时候将构造函数声明为private?
148.如何禁止自动生成拷贝构造函数?
149.assert与NDEBUGE
150.Denug和release的区别
151.main函数有没有返回值
152.写一个比较大小的模板函数
153.c++怎么实现一个函数先于main函数运行
154.虚函数与纯虚函数的区别在于
155.智能指针怎么用?智能指针出现循环引用怎么解决?
156.strcpy函数和strncpy函数的区别?哪个函数更安全?
157.为什么要用static_cast转换而不用c语言中的转换?
158.成员函数里memset(this,0,sizeof(*this))会发生什么
159.方法调用的原理(栈,汇编)
160.MFC消息处理如何封装的?
161.回调函数的作用
162.随机数的生成
II.操作系统
1.操作系统特点
2.什么是进程
3.进程
4.进程与线程的区别
5.进程状态转换图
6.进程的创建过程?需要哪些函数?需要哪些数据结构?
7.进程创建子进程,fork详解
8.子进程和父进程怎么通信?
9.进程和作业的区别?
10.死锁是什么?必要条件?如何解决?
11.鸵鸟策略
12.银行家算法
13.进程间通信方式有几种,他们之间的区别是什么?
14.线程同步的方式?怎么用?
15.页和段的区别?
16.孤儿进程和僵尸进程的区别?怎么避免这两类进程?守护进程?
17.守护进程是什么?怎么实现?
18.线程和进程的区别?线程共享的资源是什么?
19.线程比进程具有哪些优势?
20.什么时候用多进程?什么时候用多线程?
21.协程是什么?
22.递归锁?
23.用户态到内核态的转化原理?
24.中断的实现与作用,中断的实现过程?
25.系统中断是什么,用户态和内核态的区别
26.CPU中断
27.执行一个系统调用时,OS发生的过程,越详细越好1.执行用户程序(如:fork) 
28.函数调用和系统调用的区别?
29.经典同步问题解法:生产者与消费者问题,哲学家进餐问题,读者写者问题。
30.虚拟内存?使用虚拟内存的优点?什么是虚拟地址空间?
31.线程安全?如何实现?
32.linux文件系统
33.常见的IO模型,五种?异步IO应用场景?有什么缺点?
34.IO复用的原理?零拷贝?三个函数?epoll 的 LT 和 ET 模式的理解。
35.Linux是如何避免内存碎片的
36.递归的原理是啥?递归中遇到栈溢出怎么解决
37.++i是否是原子操作
38.缺页中断,页表寻址
39.LRU的实现
40.内存分区
41.伙伴系统相关
42.I/O控制方式
43.Spooling技术
44.通道技术
45.共享内存的实现
46.计一个线程池,内存池
III.Linux
1.Inode节点
2.Linux软连接、硬链接,删除了软连接的源文件软连接可用?
3.Linux系统应用程序的内存空间是怎么分配的,用户空间多大,内核空间多大?
4.Linux的共享内存如何实现
5.文件处理grep,awk,sed这三个命令必知必会
6.查询进程占用CPU的命令
7.一个程序从开始运行到结束的完整过程
8.一般情况下在Linux/windows平台下栈空间的大小
9.Linux重定向
10.Linux常用命令
IV.网络
一、物理层
二、数据链路层
三、网络层
1.路由器的功能?
2.ip报文如何从下向上交付
3.ip地址有什么用,ip地址和mac地址, 为什么需要IP地址
4.ARP协议的作用
5.NAT的原理,外网与内网或内网之间的通信中如何区分不同IP的数组包
6.RIP路由协议
7.为什么使用IP地址通信
8.子网掩码有什么用?
9.子网划分的方法
四、运输层
1.TCP协议有几大计时器?
2.详细说一下TCP协议,三次握手传输的内容?13种状态
3.TCP为啥挥手要比握手多一次?
4.为什么一定进行三次握手?
5.TCP与UDP的区别?应用场景都有哪些?
6.为什么UDP有时比TCP更有优势?
7.UDP中一个包的大小最大能多大
8.TCP 粘包
9.传输层功能
10.TCP可靠性保证
11.拥塞控制
12.TCP流量控制
13.流量控制与拥塞控制的区别?
14.time_wait与close_wait,time_wait状态持续多长时间?为什么会有time_w
15.Time_wait为什么是2MSL的时间长度
16.介绍一下ping的过程,分别用到了哪些协议
17.socket编程
18.客户端为什么不需要bind
19.send和recv的缺点
五、应用层
1.常用的网络协议?
2.网络协议各个层的网络设备?
3.讲讲浏览器输入地址后发生的全过程,以及对应的各个层次的过程
4.http与https工作方式
5.http协议,http和https的区别
6.http状态码
7.HTTP1.0与HTTP1.1的区别?
8.OSI 7层网络模型中各层的名称及其作用?
9.TCP/IP 4层网络模型名称及其作用?
10.OSI 7层网络中各层的常见协议以及协议作用?设备
11.OSI与TCP模型的区别?
12.DNS是干什么的??
13. get/post 区别
14.说一下网卡从接收到数据后发生了什么
15.send函数什么情况下会阻塞
16.常用端口号
17.https的过程
V.数据结构
1.常用查找算法?具体实现
2.常用排序算法?具体实现,哪些是稳定的,时间复杂度、空间复杂度,快速排序非递归如何实现?快排的优势?
3.图的常用算法?
4.哈夫曼编码?
5.***AVL树、B+树、红黑树、B树B+树区别,B+树应用在哪里?
6.为什么使用红黑树,什么情况使用AVL树。红黑树比AVL树有什么优点。
7.单链表如何判断有环?
8.如何判断一个图是否连同?
9.hash用在什么地方,解决hash冲突的几种方法?负载因子?
10.n个节点的二叉树的所有不同构的个数
11.二叉树的公共祖先,排序二叉树的公共祖先
12.节点的最大距离
13.把一颗二叉树原地变成一个双向链表
14.二叉树的所有路径
15.二叉树中寻找每一层中最大值?
16.最大深度、最小深度、会否是平衡树
17.二叉树中叶子节点的数量
18.交换左右孩子、二叉树镜像
19.两个二叉树是否相等
20.是否为完全二叉树
21.是否为对称二叉树
22.判断B是否为A的子树
23.构建哈夫曼树
24.手写单链表反转?删除指定的单链表的一个节点
25.实现一个循环队列
26.Top K问题
27.求一颗树的最大距离
28.KMP
29.数组和链表的区别?
30.逆序对思路
31.100个有序数组合并
32.使用递归和非递归求二叉树的深度
33.索引、链表的优缺点?
34.找一个点为中心的圆里包含的所有的点。
35.字典树的理解
36.快速排序的优化
37.海量数据的bitmap使用原理
VI.算法
1.动态规划,最长公共子序列
2.分治与递归
3.贪心算法,背包问题
4.BFS,DFS,地杰斯特拉算法,佛洛依德算法
5.动态规划的回文字符串?
6.排序算法?时间复杂度?稳定性算法?
7.查找算法
8.字符串匹配?
9.求一个数开根号(二分)
10.万个数找到第20个大小?
11.设计抢红包算法
12.字符串中最长不重复子串
13.动态规划与分支界限的差异,背包问题和分支界限的差异
14.出1-n的子集。比如123,有1,2,3,12,13,123,23.
VII.数据库
1.事务是什么
2.分布式事务
3.一二三范式
4.数据库的索引类型,数据库索引的作用
5.聚集索引和非聚集索引的区别
6.唯一性索引和主码索引的区别
7.数据库引擎,innodb和myisam的特点与区别
8.关系型和非关系型数据库的区别
9.数据库的隔离级别
10.数据库连接池的作用
11.数据的锁的种类,加锁的方式
12.数据库union join的区别
13.Inner join,left outter join,right outter join之间的区别
VIII.设计模式
1.单例模式
2.手写线程安全的单例模式?
3.工厂模式
4.装饰器模式
5.订阅/发布模式
6.观察者模式
7.MVC模式
IX.多线程编程
X.HR问题
C++ 1. 引用和指针的区别? 1) 指针是一个实体,需要分配内存空间。引用只是变量的别名,不需要分配内存空间。 2) 引用在定义的时候必须进行初始化,并且不能够改变。指针在定义的时候不一定要 初始化,并且指向的空间可变。(注:不能有引用的值不能为 NULL) 3) 有多级指针,但是没有多级引用,只能有一级引用。 4) 指针和引用的自增运算结果不一样。(指针是指向下一个空间,引用时引用的变量 值加 1) 5) sizeof 引用得到的是所指向的变量(对象)的大小,而 sizeof 指针得到的是指针本 身的大小。 6) 引用访问一个变量是直接访问,而指针访问一个变量是间接访问。 7) 使用指针前最好做类型检查,防止野指针的出现; 8) 引用底层是通过指针实现的; 9) 作为参数时也不同,传指针的实质是传值,传递的值是指针的地址;传 引用的实质是传地址,传递的是变量的地址。 2. 从汇编层去解释一下引用 1. 2. 3. 4. 5. dword ptr [ebp-4],1 eax,[ebp-4] dword ptr [ebp-8],eax int x = 1; mov int &b = x; lea mov 9: 00401048 10: 0040104F 00401052 x 的地址为 ebp-4,b 的地址为 ebp-8,因为栈内的变量内存是从高往低进行分配 的。所以 b 的地址比 x 的低。lea eax,[ebp-4] 这条语句将 x 的地址 ebp-4 放入 ea x 寄存器 mov dword ptr [ebp-8],eax 这条语句将 eax 的值放入 b 的地址 ebp-8 中 上面两条汇编的作用即:将 x 的地址存入变量 b 中,这不和将某个变量的地址存 入指针变量是一样的吗?所以从汇编层次来看,的确引用是通过指针来实现的。
3. C++中的指针参数传递和引用参数传递 1) 指针参数传递本质上是值传递,它所传递的是一个地址值。值传递过程中,被调函数的 形式参数作为被调函数的局部变量处理,会在栈中开辟内存空间以存放由主调函数传递 进来的实参值,从而形成了实参的一个副本(替身)。值传递的特点是,被调函数对形 式参数的任何操作都是作为局部变量进行的,不会影响主调函数的实参变量的值(形参 指针变了,实参指针不会变)。 2) 引用参数传递过程中,被调函数的形式参数也作为局部变量在栈中开辟了内存空间,但 是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参(本体)的任何 操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量(根据别 名找到主调函数中的本体)。因此,被调函数对形参的任何操作都会影响主调函数中的 实参变量。 3) 引用传递和指针传递是不同的,虽然他们都是在被调函数栈空间上的一个局部变量,但 是任何对于引用参数的处理都会通过一个间接寻址的方式操作到主调函数中的相关变 量。而对于指针传递的参数,如果改变被调函数中的指针地址,它将应用不到主调函数 的相关变量。如果想通过指针参数传递来改变主调函数中的相关变量(地址),那就得 使用指向指针的指针或者指针引用。 4) 从编译的角度来讲,程序在编译时分别将指针和引用添加到符号表上,符号表中记录的 是变量名及变量所对应地址。指针变量在符号表上对应的地址值为指针变量的地址值, 而引用在符号表上对应的地址值为引用对象的地址值(与实参名字不同,地址相同)。 符号表生成之后就不会再改,因此指针可以改变其指向的对象(指针变量中的值可以改), 而引用对象则不能修改。
4. 形参与实参的区别? 1) 形参变量只有在被调用时才分配内存单元,在调用结束时, 即刻释放所分配的内存 单元。因此,形参只有在函数内部有效。 函数调用结束返回主调函数后则不能再使 用该形参变量。 2) 实参可以是常量、变量、表达式、函数等, 无论实参是何种类型的量,在进行函数 调用时,它们都必须具有确定的值, 以便把这些值传送给形参。 因此应预先用赋 值,输入等办法使实参获得确定值,会产生一个临时变量。 3) 实参和形参在数量上,类型上,顺序上应严格一致, 否则会发生“类型不匹配”的错 误。 4) 函数调用中发生的数据传送是单向的。 即只能把实参的值传送给形参,而不能把形 参的值反向地传送给实参。 因此在函数调用过程中,形参的值发生改变,而实参中 的值不会变化。 5) 当形参和实参不是指针类型时,在该函数运行时,形参和实参是不同的变量,他们 在内存中位于不同的位置,形参将实参的内容复制一份,在该函数运行结束的时候 形参被释放,而实参内容不会改变。 1) 值传递:有一个形参向函数所属的栈拷贝数据的过程,如果值传递的对象是类对象 或是大的结构体对象,将耗费一定的时间和空间。(传值) 2) 指针传递:同样有一个形参向函数所属的栈拷贝数据的过程,但拷贝的数据是一个 固定为 4 字节的地址。(传值,传递的是地址值) 3) 引用传递:同样有上述的数据拷贝过程,但其是针对地址的,相当于为该数据所在 的地址起了一个别名。(传地址) 4) 效率上讲,指针传递和引用传递比值传递效率高。一般主张使用引用传递,代码逻 辑上更加紧凑、清晰。 5. static 的用法和作用? 1.先来介绍它的第一条也是最重要的一条:隐藏。(static 函数,static 变量均可) 当同时编译多个文件时,所有未加 static 前缀的全局变量和函数都具有全局可见性。
2.static 的第二个作用是保持变量内容的持久。(static 变量中的记忆功能和全局生存期) 存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。 共有两种变量存储在静态存储区:全局变量和 static 变量,只不过和全局变量比起来, static 可以控制变量的可见范围,说到底 static 还是用来隐藏的。 3.static 的第三个作用是默认初始化为 0(static 变量) 其实全局变量也具备这一属性,因为全局变量也存储在静态数据区。在静态数据区,内 存中所有的字节默认值都是 0x00,某些时候这一特点可以减少程序员的工作量。 4.static 的第四个作用:C++中的类成员声明 static 1) 函数体内 static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被 分配一次,因此其值在下次调用时仍维持上次的值; 2) 在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数 访问; 3) 在模块内的 static 函数只可被这一模块内的其它函数调用,这个函数的使用范围被 限制在声明它的模块内; 4) 在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝; 5) 在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能 访问类的 static 成员变量。 类内: 6) static 类对象必须要在类外进行初始化,static 修饰的变量先于对象存在,所以 static 修饰的变量要在类外初始化; 7) 由于 static 修饰的类成员属于类,不属于对象,因此 static 类成员函数是没有 this 指针的,this 指针是指向本对象的指针。正因为没有 this 指针,所以 static 类成员函 数不能访问非 static 的类成员,只能访问 static 修饰的类成员; 8) static 成员函数不能被 virtual 修饰,static 成员不属于任何对象或实例,所以加上 vi rtual 没有任何实际意义;静态成员函数没有 this 指针,虚函数的实现是为每一个对 象分配一个 vptr 指针,而 vptr 是通过 this 指针调用的,所以不能为 virtual;虚函数 的调用关系,this->vptr->ctable->virtual function 6. 静态变量什么时候初始化 1) 初始化只有一次,但是可以多次赋值,在主程序之前,编译器已经为其分配好了内 存。 2) 静态局部变量和全局变量一样,数据都存放在全局区域,所以在主程序之前,编译 器已经为其分配好了内存,但在 C 和 C++中静态局部变量的初始化节点又有点不太
一样。在 C 中,初始化发生在代码执行之前,编译阶段分配好内存之后,就会进行 初始化,所以我们看到在 C 语言中无法使用变量对静态局部变量进行初始化,在程 序运行结束,变量所处的全局内存会被全部回收。 3) 而在 C++中,初始化时在执行相关代码时才会进行初始化,主要是由于 C++引入对 象后,要进行初始化必须执行相应构造函数和析构函数,在构造函数或析构函数中 经常会需要进行某些程序中需要进行的特定操作,并非简单地分配内存。所以 C++ 标准定为全局或静态对象是有首次用到时才会进行构造,并通过 atexit()来管理。在 程序结束,按照构造顺序反方向进行逐个析构。所以在 C++中是可以使用变量对静 态局部变量进行初始化的。 7. const? 1) 阻止一个变量被改变,可以使用 const 关键字。在定义该 const 变量时,通常需要对 它进行初始化,因为以后就没有机会再去改变它了; 2) 对指针来说,可以指定指针本身为 const,也可以指定指针所指的数据为 const,或 二者同时指定为 const; 3) 在一个函数声明中,const 可以修饰形参,表明它是一个输入参数,在函数内部不 能改变其值; 4) 对于类的成员函数,若指定其为 const 类型,则表明其是一个常函数,不能修改类 的成员变量,类的常对象只能访问类的常成员函数; 5) 对于类的成员函数,有时候必须指定其返回值为 const 类型,以使得其返回值不为“左 6) 值”。 const 成员函数可以访问非 const 对象的非 const 数据成员、const 数据成员,也可以 访问 const 对象内的所有数据成员; 7) 非 const 成员函数可以访问非 const 对象的非 const 数据成员、const 数据成员,但不 可以访问 const 对象的任意数据成员; 8) 一个没有明确声明为 const 的成员函数被看作是将要修改对象中数据成员的函数, 而且编译器不允许它为一个 const 对象所调用。因此 const 对象只能调用 const 成员 函数。 9) const 类型变量可以通过类型转换符 const_cast 将 const 类型转换为非 const 类型; 10) const 类型变量必须定义的时候进行初始化,因此也导致如果类的成员变量有 const 类型的变量,那么该变量必须在类的初始化列表中进行初始化; 11) 对于函数值传递的情况,因为参数传递是通过复制实参创建一个临时变量传递进函 数的,函数内只能改变临时变量,但无法改变实参。则这个时候无论加不加 const 对实参不会产生任何影响。但是在引用或指针传递函数调用中,因为传进去的是一 个引用或指针,这样函数内部可以改变引用或指针所指向的变量,这时 const 才是 实实在在地保护了实参所指向的变量。因为在编译阶段编译器对调用函数的选择是 根据实参进行的,所以,只有引用传递和指针传递可以用是否加 const 来重载。一 个拥有顶层 const 的形参无法和另一个没有顶层 const 的形参区分开来。
8. const 成员函数的理解和应用? 1 const Stock & Stock::topval (②const Stock & s) ③const ①处 const:确保返回的 Stock 对象在以后的使用中不能被修改 ②处 const:确保此方法不修改传递的参数 S ③处 const:保证此方法不修改调用它的对象,const 对象只能调用 const 成员函数, 不能调用非 const 函数 9. 指针和 const 的用法 1) 当 const 修饰指针时,由于 const 的位置不同,它的修饰对象会有所不同。 2) int *const p2 中 const 修饰 p2 的值,所以理解为 p2 的值不可以改变,即 p2 只能指向固 定的一个变量地址,但可以通过*p2 读写这个变量的值。顶层指针表示指针本身是一 个常量 int const *p1 或者 const int *p1 两种情况中 const 修饰*p1,所以理解为*p1 的值不可以 改变,即不可以给*p1 赋值改变 p1 指向变量的值,但可以通过给 p 赋值不同的地址改 变这个指针指向。底层指针表示指针所指向的变量是一个常量。 int const *const p; 3) 4) 10. mutable 1) 如果需要在 const 成员方法中修改一个成员变量的值,那么需要将这个成员变量修饰 为 mutable。即用 mutable 修饰的成员变量不受 const 成员方法的限制; 2) 可以认为 mutable 的变量是类的辅助状态,但是只是起到类的一些方面表述的功能, 修改他的内容我们可以认为对象的状态本身并没有改变的。实际上由于 const_cast 的 存在,这个概念很多时候用处不是很到了。 11. extern 用法? 1) 2) extern 修饰变量的声明 如果文件 a.c 需要引用 b.c 中变量 int v,就可以在 a.c 中声明 extern int v,然后就可以 引用变量 v。 extern 修饰函数的声明 如果文件 a.c 需要引用 b.c 中的函数,比如在 b.c 中原型是 int fun(int mu),那么就可以 在 a.c 中声明 extern int fun(int mu),然后就能使用 fun 来做任何事情。就像变量的
声明一样,extern int fun(int mu)可以放在 a.c 中任何地方,而不一定非要放在 a.c 的文件作用域的范围中。 3) extern 修饰符可用于指示 C 或者 C++函数的调用规范。 比如在 C++中调用 C 库函数,就需要在 C++程序中用 extern “C”声明要引用的函 数。这是给链接器用的,告诉链接器在链接的时候用 C 函数规范来链接。主要原因是 C++和 C 程序编译完成后在目标代码中命名规则不同。 12. int 转字符串字符串转 int?strcat,strcpy,strncpy,memset,memcpy 的内 部实现? c++11 标准增加了全局函数 std::to_string 可以使用 std::stoi/stol/stoll 等等函数 strcpy 拥有返回值,有时候函数原本不需要返回值,但为了增加灵活性如支持链式表达, 13. 深拷贝与浅拷贝? 1) 浅复制 —-只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用, 我们把这种拷贝叫做“(浅复制)浅拷贝”,换句话说,浅复制仅仅是指向被复制的 内存地址,如果原地址中对象被改变了,那么浅复制出来的对象也会相应改变。 深复制 —-在计算机中开辟了一块新的内存地址用于存放复制的对象。 2) 在某些状况下,类内成员变量需要动态开辟堆内存,如果实行位拷贝,也就是把对 象里的值完全复制给另一个对象,如 A=B。这时,如果 B 中有一个成员变量指针 已经申请了内存,那 A 中的那个成员变量也指向同一块内存。这就出现了问题:当
B 把内存释放了(如:析构),这时 A 内的指针就是野指针了,出现运行错误。 14. C++模板是什么,底层怎么实现的? 1) 编译器并不是把函数模板处理成能够处理任意类的函数;编译器从函数模板通过具 体类型产生不同的函数;编译器会对函数模板进行两次编译:在声明的地方对模板 代码本身进行编译,在调用的地方对参数替换后的代码进行编译。 2) 这是因为函数模板要被实例化后才能成为真正的函数,在使用函数模板的源文件中 包含函数模板的头文件,如果该头文件中只有声明,没有定义,那编译器无法实例 化该模板,最终导致链接错误。 15. C 语言 struct 和 C++struct 区别 1) C 语言中:struct 是用户自定义数据类型(UDT);C++中 struct 是抽象数据类型(ADT), 支持成员函数的定义,(C++中的 struct 能继承,能实现多态)。 2) C 中 struct 是没有权限的设置的,且 struct 中只能是一些变量的集合体,可以封装 数据却不可以隐藏数据,而且成员不可以是函数。 3) C++中,struct 的成员默认访问说明符为 public(为了与 C 兼容),class 中的默认 4) 访问限定符为 private,struct 增加了访问权限,且可以和类一样有成员函数。 struct 作为类的一种特例是用来自定义数据结构的。一个结构标记声明后,在 C 中 必须在结构标记前加上 struct,才能做结构类型名 16. 虚函数可以声明为 inline 吗? 1) 虚函数用于实现运行时的多态,或者称为晚绑定或动态绑定。而内联函数用于提高 效率。内联函数的原理是,在编译期间,对调用内联函数的地方的代码替换成函数 代码。内联函数对于程序中需要频繁使用和调用的小函数非常有用。 2) 虚函数要求在运行时进行类型确定,而内敛函数要求在编译期完成相关的函数替换; 17. 类成员初始化方式?构造函数的执行顺序 ?为什么用成员初始 化列表会快一些? 1) 赋值初始化,通过在函数体内进行赋值初始化;列表初始化,在冒号后使用初始化 列表进行初始化。 这两种方式的主要区别在于: 对于在函数体中初始化,是在所有的数据成员被分配内存空间后才进行的。
分享到:
收藏