C++面试题面经

  1. STL.

    1. 顺序性容器:元素间有顺序关系的线性表。

      1. vector动态数组,线性结构,连续存储,随机访问,检索快,只能在后端添加删除

      2. list双向循环链表,不连续存储,不支持随机访问,支持任意位置插入删除

      3. deque双向队列,支持随机 访问,支持内部插入删除

    2. 关联式容器:非线性,包括二叉树结构和哈希表结构。有排序功能

      1. set集合,元素值唯一,按序排列

      2. multiset多重集合,不要求元素唯一

      3. unordered_set

      4. map键值对,键唯一且有序。其按链表存储。底层为红黑树

      5. multimap,键可以不唯一

      6. unordered_map,键值对不根据key大小排序,无序,可以按插入顺序建立哈希表

    3. 容器适配器:stack,queue,priority_queue

      1. stack栈,先进后出

      2. queue队列,先进先出

      3. priority_queue

  • 二叉树特例:堆和红黑树。

    • 堆分为最大堆和最小堆,很多需要快速找到最大值或者最小值的问题都可以用堆来解决。

    • 红黑树是把树种的节点定义为红,黑两种颜色,并通过规则确保从根节点到叶节点的最长路径的长度不超过最短路径的两倍

    • c++的STL中,set,multiset,map,multimap等数据结构都是基于红黑树实现的

        

  1. 虚函数virtual

    1. c++虚函数主要作用是“运行时多态”,父类中提供虚函数的实现,为子类提供默认的函数实现

    2. 子类可以重写父类的虚函数实现子类的特殊化。纯虚函数“只提供声明没有实现”,是对子类的约束,是“接口继承”

    3. 纯虚函数被称为“抽象类”。抽象类不能使用new出对象,只有实现了这个纯虚函数的子类才能new出对象

  1. set,map底层数据结构,红黑树的细节。map,m[1]="str";这句低层是怎么实现的,发生了什么

  2. b+树的细节,查找过程

  3. 多态:多态性可以简单概括为一个接口,多种方法。通常是指对于同一个消息,同一种调用,在不同的场合不同情况下,执行不同的行为

    1. 静态多态性,包括函数重载,运算符重载

    2. 动态多态性,虚函数。c++通过虚函数实现动态联编

    3. 基类函数为virtual,子类派生也是virtual。

    4. 派生类要对虚函数重定义,应保持相同参数个数,相同参数类型,相同返回值类型

  4. 宏定义和替换: #define 标识符  字符串      #define  标识符(参数列表)   字符串。

    1. 编译前进行,不分配空间

    2. 结尾不需要分号

  5. 文件包含:

    1. #include    <>表示标准头文件。编译器将会在预定义位置集合中查找头文件

    2. #include "my_file.h"  非系统头文件,通常从源文件所在路径查找

  6. 全局变量和局部变量:

    1. 全局变量作用域全局,或用extern 表示

    2. 局部变量作用域部分,若与全局变量同名,屏蔽全局变量

  7. static作用

    1. 隐藏,当同事编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。若加了static,会对其他源文件隐藏

    2. 默认初始化为0

    3. 静态局部变量生存周期为整个源程序,但其作用域仍然与局部变量相同,只能在定义该变量的函数内使用该变量。退出函数后,该变量还存在,但不能使用

    4. 类中static作用:表示属于一个类而不是属于此类任何特定对象的变量和函数

      1. 静态数据成员(静态(全局)存储区)

        1. static数据成员独立于该类的任意对象而存在,只与该类关联。当某类修改了静态成员变量,修改值对其他所有实例所见

        2. static数据成员必须在类定义体的外部定义

        3. 非静态成员在类对象中的排列顺序和声明顺序一致,任何在其中间声明的静态成员都不会被放进对象布局。静态数据成员存放在程序的全局(静态)存储中,和个别类对象无关。

      2. 静态成员函数:属于类的一部分,为整个类服务,不是为某一对象服务

        1. 普通成员函数总是为具体某个对象服务,因为普通成员函数都隐含了一个this指针,this指针指向对象本身

        2. static成员函数不具有this指针,为整个类服务。因而无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,只能调用静态成员和静态成员函数

        3. static不是任何对象组成部分,所以static成员函数不能声明为const。将成员函数声明为const就承诺不会修改函数所属的对象,而static不属于任何对象

        4. 非静态成员函数可以访问静态成员变量和静态成员函数。静态成员函数没有this指针额外开销,所以速度快些

  8. const常量,定义后无法修改,所以定义的时候必须初始化

    1. 全局作用域定义非const变量,在整个程序中都可以访问

    2. 全局作用域声明const变量是定义该对象的文件的局部变量,该变量只存在于当前变量中,不能被其他文件访问。通过将const变更为extern可以再整个程序中访问、

    3. const代替#define的值替换功能

      1. const有数据类型,宏定义没有

      2. const只会产生更小的目标哦代码,因为宏是直接替换

    4. 指针和const修饰符

      1. 指向const的指针:const double *p;  p是一个指针,指向const double,也就是p可以指向任何东西,但指向的东西是不能变的,是const

      2. const指针:使指针本身成为一个const指针,必须吧const标明的部分放在*右边; double d=1.0;  double * const p=&d;读作p是指针,指向double 的const指针,指针本身是const,必须初始化,不能改变指向,但可以改变指向的值的内容。

    5. 修饰函数参数与返回值

      1. const修饰返回值:若返回值是值类型(非指针,引用),用不用const无所谓。若是返回指针类型。函数不能返回指向局部栈变量的指针,因为在函数返回后它是无效的,栈也被清理了。可返回的指针是指向堆中分配的存储空间的指针或指向静态存储区的指针,函数返回后它仍然有效

      2. const用来修饰函数的参数:用值传递,表示参数在函数内也不会修改

    6. const在类中的应用

      1. 类成员函数后面加const,为了确保该函数成员可作用域const对象身上,表示const成员函数不能修改调用该函数的对象。const对象,指向const对象的指针或引用只能调用其const成员函数。

      2. const数据成员:常量成员变量必须在构造函数的成员初始化列表中进行初始化(必须有构造函数)。当 常量数据成员同时被声明为static时,此时可以使用外部 初始化。类可以创建多个对象,不同的对象其const数据成员的值可以不同,所以不能在类声明时初始化const数据成员

  9. 内存管理与释放:主要内存有:栈区,堆区,全局(静态)存储区,文字常量区,代码区

    1. 堆和栈的区别:

      1. 栈区:类似于数据结构栈,编译器自动分配释放,存放函数的参数值,局部变量的值等。如函数中声明一个局部变量int b;

      2. 堆区:程序员分配释放,否则程序结束自动收回。分配方式类似于链表。速度慢,容易产生内存碎片,用起来方便。malloc,new在堆上分配空间

        1. char *p =(char*)malloc(10);   p本身在栈中,他们指向在堆上分配的内存。

  10. c++内存管理:malloc/free, new/delete

    1. int *p=new int;//无初始化    int *p=new int(); //p指向一个初始化为0的int值

    2. const int *p = new const int(1024);  //动态创建的const对象必须在创建时初始化,并且一经初始化,其值就不能再修改。

    3. malloc/free与new/delete的区别

      1. 操作对象不同:malloc/free是c/c++的标准库函数,new/delete是c++的运算符

        1. new执行过程是:先调用名为operator new的标准库函数,分配足够大的原始未类型化的内存,以保存指定类型的一个对象;接下来运行该类型的一个构造函数,用于指定初始化式构造对象;最后返回指向新分配并构造的对象的指针

        2. delete的执行过程是:先对sp指向的对象运行适当的析构函数;然后通过调用名为operator delete的标准库函数释放该对象所用内存

        3. 以上operator new与operator delete分别对应于malloc与free

      2. 用法上也不同

        1. malloc不识别需要申请的内存是什么类型,只关心内存的总字节数。返回值是void*型,所以在调用malloc时要显示转换成所需要的类型

        2. free(p)用来释放指针,如果p是NULL,对p释放多少次都没问题,若不是NULL,对p连续释放两次就会导致程序运行错误。

        3. 用new创建对象数组,只能使用对象的无参数构造函数,释放对象数组时delete p[]。。obj *p=new obj[100](1);//创建100个动态对象的同时赋初始值1

      3. 不同之处总结如下:

        1. malloc与free是c/c++标准库函数,new/delete是c++运算符

        2. new自动计算需要分配的空间,而malloc需要手工计算字节数

        3. new类型是安全的,malloc不是

        4. new调用operator new分配足够空间,并调用相关对象的构造函数,而malloc不能调用构造函数;delete将调用该实例的析构函数,然后调用类的operator delete,以释放该实例占用的空间,而free不能调用析构函数

        5. malloc/free需要库文件支持,new/delete不需要

  11. 引用:对象的另一个名字。c++规定一旦引用,就必须把它跟一个变量绑定起来,并不能修改这个绑定。引用不能为空

    1. 成员初始化列表:c++中成员变量的初始化顺序与变量在类型中的声明顺序相同,而与他们在构造函数的初始化列表中的顺序无关

  12.  

底下是旷世面试的问题

虚函数是什么原理,c++是如何实现多态的。

有没有用过智能指针,智能指针的原理和作用。

STL当中的容器用过哪些,了解哪些都是什么作用大概说下。

知道哈希函数么,STL当中那个容器是哈希实现的哪个是红黑树实现的,具体的复杂度是多少。

给你一个对象你只知道他的类型,你也知道这个类型只有一个方法,但是你不知道这个方法的名称,你该怎么调用这个方法?

析构函数可以是虚函数么?为什么要将析构函数设为虚函数,可以将所有的析构函数设置为虚函数么?

 

以C++为例,列出笔试一般会考的内容:

  • 语言基础,C++中的定义,指针,模板,多态,重载等(尤其是多态,给定一个程序,基类子类有不同实现,考虑输出结果,这一类的题目面试题极为高频)

  • TCP/IP协议及其编程:计算机网络基础,socket编程,其中子网划分,七层协议(例如交换机属于数据链路层一类题目),五层协议,协议名称及其作用,常用端口号,https1.0 1.1特性与区别,三次握手四次挥手(可能出现的服务器攻击),加密(对称,非对称),IO复用等

  • 操作系统:进程通信方式(linux/windows,每种方式的特点),线程通信(linux/windows),进程与线程区别,页面置换策略(考察置换几次),进程/线程状态图,进程调度方式,死锁(必要条件,哲学家就餐,银行家,读者写者问题)

  • 数据库:索引作用,应该/不应该创建索引的列,索引底层实现,sql语法,常见引擎特点,事务特点,隔离级别(引擎默认级别),隔离级别的问题,锁等

  • 智力题:大厂一般笔试面试喜欢出,重在考察思维能力,也是为了选出潜力更大的人来。如果欠缺可以在牛客上刷题

  • 算法:剑指offer,leetcode,左神的书和视频,任意两个搞定都没问题

你可能感兴趣的:(#,c/c++)