说明:
- 面试群,群号: 228447240
- 面试题来源于网络书籍,公司题目以及博主原创或修改(题目大部分来源于各种公司);
- 文中很多题目,或许大家直接编译器写完,1分钟就出结果了。但在这里博主希望每一个题目,大家都要经过认真思考,答案不重要,重要的是通过题目理解所考知识点,好应对题目更多的变化;
- 博主与大家一起学习,一起刷题,共同进步;
- 写文不易,麻烦给个三连!!!
前面1-15已经是C/C++,但是由于前面写的比较混乱,把八股文和题目混在了一起,所以从这一篇开始重新整理重新写,前面1-15也就可以选看了,希望多多支持!
目录
4.说一说strcpy、sprintf与memcpy这三个函数的不同之处
1.C++中标准库是什么
答案:
1) C++
标准库可以分为两部分:
标准函数库: 这个库是由通用的、独立的、不属于任何类的函数组成的。函数库继承自
C
语言。
面向对象类库: 这个库是类及其相关函数的集合。
2)
输入
/
输出
I/O
、字符串和字符处理、数学、时间、日期和本地化、动态分配、其他、宽字符函数
3)
标准的
C++ I/O
类、
String
类、数值类、
STL
容器类、
STL
算法、
STL
函数对象、
STL
迭代器、
STL分配器、本地化库、异常处理类、杂项支持库
2.什么情况用指针当参数,什么时候用引用
答案:
1)
使用引用参数的主要原因有两个:
- 程序员能修改调用函数中的数据对象
- 通过传递引用而不是整个数据–对象,可以提高程序的运行速度
2)
一般的原则:
- 对于使用引用的值而不做修改的函数:
- 如果数据对象很小,如内置数据类型或者小型结构,则按照值传递;
- 如果数据对象是数组,则使用指针(唯一的选择),并且指针声明为指向const的指针;
- 如果数据对象是较大的结构,则使用const指针或者引用,已提高程序的效率。这样可以节省结构所需的时间和空间;
- 如果数据对象是类对象,则使用const引用(传递类对象参数的标准方式是按照引用传递);
3)
对于修改函数中数据的函数:
- 如果数据是内置数据类型,则使用指针
- 如果数据对象是数组,则只能使用指针
- 如果数据对象是结构,则使用引用或者指针
- 如果数据是类对象,则使用引用
3.如何设计一个类计算子类的个数(大厂原题)
答案:
1
、为类设计一个
static
静态变量
count
作为计数器;
2
、类定义结束后初始化
count;
3
、在构造函数中对
count
进行
+1;
4
、 设计拷贝构造函数,在进行拷贝构造函数中进行
count +1
;
5
、设计复制构造函数,在进行复制函数中对
count+1
;
6
、在析构函数中对
count
进行
-1
;
4.说一说strcpy、sprintf与memcpy这三个函数的不同之处
答案:
1)
操作对象不同
①
strcpy
的两个操作对象均为字符串
②
sprintf
的操作源对象可以是多种数据类型,目的操作对象是字符串
③
memcpy
的两个对象就是两个任意可操作的内存地址,并不限于何种数据类型。
2)
执行效率不同
memcpy
最高,
strcpy
次之,
sprintf
的效率最低。
3)
实现功能不同
①
strcpy
主要实现字符串变量间的拷贝
②
sprintf
主要实现其他数据类型格式到字符串的转化
③
memcpy
主要是内存块间的拷贝。
5.道数组和指针的区别
答案:
1)
数组在内存中是连续存放的,开辟一块连续的内存空间;数组所占存储空间:
sizeof
(数组名);数组大小:sizeof(
数组名
)/sizeof(
数组元素数据类型
)
;
2)
用运算符
sizeof
可以计算出数组的容量(字节数)。
sizeof(p),p
为指针得到的是一个指针变量的字节数,而不是p
所指的内存容量。
3)
编译器为了简化对数组的支持,实际上是利用指针实现了对数组的支持。具体来说,就是将表达式中的数组元素引用转换为指针加偏移量的引用。
4)
在向函数传递参数的时候,如果实参是一个数组,那用于接受的形参为对应的指针。也就是传递过去是数组的首地址而不是整个数组,能够提高效率;
5)
在使用下标的时候,两者的用法相同,都是原地址加上下标值,不过数组的原地址就是数组首元素的地址是固定的,指针的原地址就不是固定的。
6.如何阻止一个类被实例化?有哪些方法
答案:
1)
将类定义为抽象基类或者将构造函数声明为
private
;
2)
不允许类外部创建类对象,只能在类内部创建对象
7.为什么友元函数必须在类内部声明?
答案:
因为编译器必须能够读取这个结构的声明以理解这个数据类型的大小、行为等方面的所有规则。
有一条规则在任何关系中都很重要,那就是谁可以访问我的私有部分。
8.友元函数和友元类的基本情况
答案:
友元提供了不同类的成员函数之间、类的成员函数和一般函数之间进行数据共享的机制。通过友元,一个不同函数或者另一个类中的成员函数可以访问类中的私有成员和保护成员。友元的正确使用能提高程序的运行效率,但同时也破坏了类的封装性和数据的隐藏性,导致程序可维护性变差。
1
)友元函数
友元函数是定义在类外的普通函数,不属于任何类,可以访问其他类的私有成员。但是需要在类的定义中声明所有可以访问它的友元函数。
一个函数可以是多个类的友元函数,但是每个类中都要声明这个函数。
2
)友元类
友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。
但是另一个类里面也要相应的进行声明
注意:
(1)
友元关系不能被继承。
(2)
友元关系是单向的,不具有交换性。若类
B
是类
A
的友元,类
A
不一定是类
B
的友元,要看在类中是否有相应的声明。
(3)
友元关系不具有传递性。若类
B
是类
A
的友元,类
C
是
B
的友元,类
C
不一定是类
A
的友元,同样要看类中是否有相应的申明
9.为什么不能把所有的函数写成内联函数
答案:
内联函数以代码复杂为代价,它以省去函数调用的开销来提高执行效率。所以一方面如果内联函数体内代码执行时间相比函数调用开销较大,则没有太大的意义;另一方面每一处内联函数的调用都要复制代码,消耗更多的内存空间,因此以下情况不宜使用内联函数:
- 函数体内的代码比较长,将导致内存消耗代价
- 函数体内有循环,函数执行时间要比函数调用开销大
10.类的对象存储空间?
答案:
非静态成员的数据类型大小之和。
编译器加入的额外成员变量(如指向虚函数表的指针)。
为了边缘对齐优化加入的
padding
。
空类
(
无非静态数据成员
)
的对象的
size
为
1,
当作为基类时
, size
为
0。
11.什么是内存池
答案:
内存池(
Memory Pool
) 是一种
内存分配
方式。通常我们习惯直接使用
new
、
malloc
等申请内存,这样做的缺点在于:由于所申请内存块的大小不定,当频繁使用时会造成大量的内存碎片并进而降低性能。内存池则是在真正使用内存之前,先申请分配一定数量的、大小相等(
一般情况下
)
的内存块留作备用。当有新的内存需求时,就从内存池中分出一部分内存块, 若内存块不够再继续申请新的内存。这样做的一个显著优点是尽量避免了内存碎片,使得内存分配效率得到提升。
12.关于this指针你知道什么?全说出来
答案:
this指针是类的指针,指向对象的首地址。
this
指针只能在成员函数中使用,在全局函数、静态成员函数中都不能用
this
。
this
指针只有在成员函数中才有定义,且存储位置会因编译器不同有不同存储位置。
this
指针的用处
一个对象的
this
指针并不是对象本身的一部分,不会影响
sizeof(
对象
)
的结果。
this
作用域是在类内部, 当在类的非静态成员函数
中访问类的
非静态成员
的时候(全局函数,静态函数中不能使用
this
指针), 编译器会自动将对象本身的地址作为一个隐含参数传递给函数。也就是说,即使你没有写上this
指针, 编译器在编译的时候也是加上this
的,它作为非静态成员函数的隐含形参,对各成员的访问均通过
this
进行。
this
指针的使用
一种情况就是,在类的非静态成员函数中返回类对象本身的时候,直接使用
return *this
;
另外一种情况是当形参数与成员变量名相同时用于区分,如
this->n = n
(不能写成
n = n
)。
类的
this
指针有以下特点
1)this
只能在成员函数中使用,全局函数、静态函数都不能使用
this
。实际上,
成员函数默认第一个参
数
为
T * const this
2)this
在成员函数的开始前构造,在成员函数的结束后清除。这个生命周期同任何一个函数的参数是一样的,没有任何区别。当调用一个类的成员函数时,编译器将类的指针作为函数的this
参 数传递进去。