C++基础知识面试题总结
1、多态实现
2、说说C_C++区别
3、const关键字
4、malloc/free 和 new/delete区别
5、指针和引用区别
6、C++中堆和栈区别
7、关键字static
8、在C++程序中调用被C语言修饰函数,为什么要加extern “C”
解决函数名在符号表中匹配问题, 实现C++与C混合编程
若不加会出现连接错误(XX函数未定义), 因为C++语言和C语言对编译后的函数符号和外部变量符号的修饰方式不一样
代码编译过后, 连接器解析外部符号的时候就会出现无法解析外部符号的错误
加上extern “C”之后,C++编译器就会按照C语言的符号修饰规则对函数进行修饰, 连接器就能够正确解析
extern
extern 是 C_C++ 语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用
extern “C”是连接申明(linkage declaration),被extern “C”修饰的变量和函数是按照C语言方式编译和连接的
C++中对类C函数编译
C++支持函数重载, C语言不支持, 函数被C++编译后在符号库中的名字与C语言中的不同
void func(int x, int y)
C语言编译器编译后在符号库中名字为_func
C++编译器符号库中名字则会类似_func_int_int, 包含了函数名、函数参数数量及类型信息, C++就是靠这种机制来实现函数重载
9、如何防止头文件被重复包含
头文件开头结尾添加条件编译宏
#ifndef INCLUDE_HEADER_H
#define INCLUDE_HEADER_H
...
#endif
若宏INCLUDE_HEADER_H未定义, 则定义INCLUDE_HEADER_H宏, 并编译程序段
10、什么是内存泄漏? 什么是野指针? 什么是内存越界? 如何避免?
内存泄漏
内存泄漏是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费
野指针
指向不可用内存区域的指针
11、描述一下封装、继承、多态
12、堆栈缓存方式的区别
13、STL容器有哪些,常用的算法
14、什么是面向对象
面向对象
首先抽象出各种对象(各种类), 把数据和方法都封装在对象中(类), 然后各个对象之间发生相互作用
面向过程
将问题分解成若干步骤(动作), 每个步骤(动作)用一个函数来实现, 在使用时将数据传递给这些函数
15、用过的设计模式,简单举几个例子
16、如何理解智能指针,什么时候改变引用计数
17、share_ptr与weak_ptr的区别与联系
share_ptr
智能指针主要用于管理在堆上分配的内存,它将普通的指针封装为一个栈对
当栈对象的生存周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄漏
shared_ptr采用引用计数的方法,记录当前内存资源被多少个智能指针引用
该引用计数的内存在堆上分配
当新增一个时引用计数加1,当过期时引用计数减一
只有引用计数为0时,智能指针才会自动释放引用的内存资源
weak_ptr
share_ptr虽然已经很好用了,但是有一点share_ptr智能指针还是有内存泄露的情况,当两个对象相互使用一个shared_ptr成员变量指向对方,会造成循环引用,使引用计数失效,从而导致内存泄漏
weak_ptr 是一种不控制对象生命周期的智能指针, 它指向一个 shared_ptr 管理的对象
进行该对象的内存管理的是那个强引用的shared_ptr, weak_ptr只是提供了对管理对象的一个访问手段
18、表述下string的Copy-On-Write技术,写时copy
19、描述下C++的浅copy,深copy,写时copy和引用计数的copy
20、C++构造函数是否可以抛出异常
21、是否在析构函数抛出异常
22、构造函数中,成员变量一定要通过初始化列表来初始化的
23、volatile的作用
24、构造函数和析构函数可以调用虚函数吗
25、内存对齐的原则
26、内联函数有什么优点?内联函数和宏定义的区别
27、数组与指针的区别与联系,函数指针,指针函数,指针数组,数组指针
28、STL set 和 map都是基于什么实现的
29、常见的内存错误及其对策
30、三种内存对象的比较
栈对象
栈对象的优势是在适当的时候自动生成.又在适当的时候自动销毁.不需要程序员操心;
栈对象的创建速度一般较堆对象快.因为分配堆对象时.会调用operator new操作.operator new会采用某种内存空间搜索算法.而该搜索过程可能是很费时间
产生栈对象仅需要移动栈顶指针就可
栈空间容量比较小.一般是1MB~2MB.体积比较大的对象不适合在栈中分配
递归函数中最好不要使用栈对象.因为随着递归调用深度的增加.所需的栈空间也会线性增加.当所需栈空间不够时.便会导致栈溢出错误
堆对象
产生时刻和销毁时刻都要程序员精确定义.程序员对堆对象的生命具有完全的控制权
需要创建一个对象能够被多个函数所访问.但是又不想使其成为全局.那么这个时候创建一个堆对象无疑是良好的选择.然后在各个函数之间传递这个堆对象的指针.便可以实现对该对象的共享
相比于栈空间.堆的容量要大得多
当物理内存不够时.若这时还需要生成新的堆对象.通常不会产生运行时错误.而是系统会使用虚拟内存来扩展实际的物理内存
静态对象
- 全局对象
全局对象为类间通信和函数间通信提供了一种最简单的方式.虽然这种方式并不优雅
全局对象意味着不安全和高耦合.在程序中过多地使用全局对象将大大降低程序的健壮性、稳定性、可维护性和可复用性
- 类的静态成员
上面已经提到.基类及其派生类的所有对象都共享这个静态成员对象.所以当需要在这些class之间或这些class objects之间进行数据共享或通信时.这样的静态成员无疑是很好的选择.
- 静态局部对象
主要可用于保存该对象所在函数被屡次调用期间的中间状态.最显著的例子就是递归函数.我们都知道递归函数是自己调用自己的函数.若在递归函数中定义一个nonstatic局部对象.那么当递归次数相当大时.所产生的开销也是巨大的. 这是因为nonstatic局部对象是栈对象.每递归调用一次.就会产生一个这样的对象.每返回一次.就会释放这个对象.而且.这样的对象只局限于当前调用层.对于更深入的嵌套层和更浅露的外层.都是不可见的. 每个层都有自己的局部对象和参数.
在递归函数设计中.可以使用static对象替代nonstatic局部对象(即栈对象).这不仅可以减少每次递归调用和返回时产生和释放nonstatic对象的开销.而且static对象还可以保存递归调用的中间状态.并且可为各个调用层所访问
31、C++内存泄露及检测工具
32、什么时候要用虚析构函数
33、#include
34、什么是RTTI (Run-time type identification)
35、引用作为函数参数有哪些特点
36、在什么时候需要使用常引用
37、将引用作为函数返回值类型的格式、好处和需要遵守的规则
38、结构体和联合体的区别
39、重载和重写的区别
40、栈内存与文字常量区
41、struct和class的区别
42、如何判断浮点数是否相等,LONG呢
43、不允许重载的5个运算符
44、拷贝构造函数在哪几种情况下会被调用
45、什么时候必须重写拷贝构造函数
46、静态成员函数存在的意义
47、流运算符为什么不能通过类的成员函数重载
48、当一个类中没有任何成员变量和成员函数,这时sizeof(A)的A值是多少,
49、若不是零,请解释一下编译器为什么没有让他为零
50、多态的作用
51、什么函数不能声明为虚函数
构造函数
52、系统会自动和关闭的3个标准的文件是
标准输入流, stdin
标准输出流, stdout
标准错误输出流, stderr
53、说出字符常量和字符串常量的区别,并使用sizeof 计算有什么不同
54、Windows消息系统由哪几部分构成
55、assert()的作用
56、Windows的消息机制
57、SendMessage和PostMessage的区别
58、Dll和lib的区别
59、多线程如何实现通讯,如何进行同步
60、stl实现了那些排序算法
61、一元、二元仿函数的区别和使用背景
62、智能指针可以放到容器中么
63、请简述Windows内存管理的方式
64、strcpy和memcpy使用时的注意事项,strncpy、memncpy的区别
65、const和static能同时修饰成员函数吗
66、何时编译器会自动生成默认构造函数
67、何时编译器会自动生成拷贝构造函数
68、动态链接库和静态链接库的区别
69、描述一下函数调用的整个过程
70、C++ STL vector的实现机制
71、面向对象是一种思想,如何使用C语言来实现
72、C++有哪些数据类型, 为什么long和int都是4字节
73、Java和C++的区别是什么,分别用在什么场景比较好
74、函数调用类型_cedecl,_stdcall,_fastcall
75、什么是序列化和反序列化
76、用预处理指令声明一个常数, 用以表明1年终有多少秒
77、strtok函数在使用上要注意什么问题
78、char * const p ,char const * p, char const * const p区别
79、介绍一下右值引用和移动语义和完美转发
80、说说你使用的C++11的特性
81、如何区分左值和右值
左值与右值的根本区别在于能否获取内存地址
左值与右值
-
左值指既能够出现在等号左边, 也能出现在等号右边的变量
-
右值则是只能出现在等号右边的变量
左值在内存有确定存储地址、有变量名.表达式结束依然存在的值.简单来说左值就是非临时对象
右值就是在内存没有确定存储地址、没有变量名.表达式结束就会销毁的值.简单来说右值就是临时对象
82、为什么C++访问虚函数比访问普通函数慢
83、为什么需要纯虚函数
84、内联函数、构造函数、静态成员函数可以是虚函数么
85、析构函数可以调用虚函数,构造函数为什么不可以调用虚函数
86、析构函数可以是纯虚的么
87、为什么需要虚继承,虚继承的实现原理
88、迭代器和普通自指针有什么区别
89、C++4种类型转换
90、如何定义一个只能在堆上创建的类,如何定义一个只能在栈上创建的类
91、标准库函数和系统调用的区别
92、如何区分一段代码是C++还是C代码编写的
93、什么是回调函数,回调函数的使用场景
94、临时对象在什么时候会产生
95、说一下C++的返回值优化(先看右值引用)
返回值优化(Return value optimization, RVO)是C++的一项编译优化技术
删除保持函数返回值的临时对象, 可能会省略多次复制构造函数
96、protected,public,private在继承中的可见性
97、C++中为什么用模板类
98、子类不能继承父类的函数有哪些
99、虚函数的内存结构,菱形继承的虚函数内存结构
100、谈谈stl标准库的线程安全性
101、成员函数里memset(this,0,sizeof(*this))会发生什么
102、share_ptr的线程安全性
103、vector资源释放