C++常见面试题整理

编译和调试

C/C++程序编译过程

  • C/C++程序编译过程就是把C/C++代码百年城可执行文件的过程, 该过程分为4步
  • 预处理阶段
    1. 进行宏展开和宏替换
    2. 处理条件编译指令, 如#ifdef, #endif等
    3. 去掉注释
    4. 添加行号和文件名标识
    5. 保留#pargma编译器指令(#Pragma命令将设定编译器的状态或者是指示编译器完成一些特定的动作)
  • 编译阶段
    1. 编译程序所要作得工作就是通过词法分析, 语法和语义分析,在确认所有的指令都符合语法规则之后,将其翻译成等价的中间代码表示或汇编代码。
    2. 代码优化
    3. 重点关注函数压栈方式的编译处理
      1. __cdecl是C DECLaration的缩写, 表示C语言默认的函数调用方法: 所有参数从右到左依次入栈. 这些参数由调用者清除,称为手动清栈. 被调用函数不需要求调用者传递多少参数, 调用者传递过多或者过少的参数. 甚至完全不同的参数都不会产生编译阶段的错误。
      2. _stdcall 是StandardCall的缩写, 是C++的标准调用方式:所有参数从右到左依次入栈,如果是调用类成员的话, 最后一个入栈的是this指针。这些堆栈中的参数由被调用的函数在返回后清除, 使用的指令是 retnX,X表示参数占用的字节数. CPU在ret之后自动弹出X个字节的堆栈空间。称为自动清栈. 函数在编译的时候就必须确定参数个数. 并且调用者必须严格的控制参数的生成,不能多, 不能少, 否则返回后会出错。
  • 汇编阶段
    1. 汇编过程实际上指把汇编语言代码翻译成目标机器指令的过程
    2. 对于被翻译系统处理的每一个C语言源程序, 都将最终经过这一处理而得到相应的目标文件。目标文件中所存放的也就是与源程序等效的目标的机器语言代码。
    3. 目标文件由段组成. 通常一个目标文件中至少有两个段: 代码段和数据段
  • 链接阶段
    1. 将所有的目标文件代码拼接且重定位符号地址, 生成可执行文件
    2. 两种链接方式: 动态链接和静态链接

动态链接和静态链接区别

  • 静态链接

    1. 在编译时静态库和程序链接
    2. 一般命名为:libxxx.a
    3. 运行时,可执行目标文件已经装载完毕,速度快
    4. 但是多个程序需要静态库时每个都会复制一份,造成内存浪费
    5. 更新后需要重新编译
  • 动态链接

    1. 在运行时链接

    2. 一般命名: libxxx.so

    3. 运行时加载链接, 速度相对慢

    4. 运行时多个程序共享同一份动态库, 不会造成内存浪费

    5. 易更新, 无需重新编译

内存管理

new/delete和malloc/free区别

  • new是C++关键字,需要编译器支持. 而malloc是C语言库函数
  • new失败时, 会抛出bad_alloc异常. malloc会返回NULL
  • new执行时, 先分配内存, 再调用类的构造函数初始化, malloc只会分配内存
  • new无需指定分配内存大小, 编译器会根据类型信息自行计算, malloc需要在参数里指出分配内存的大小
  • new成功会直接返回所分配的对象的指针, 而malloc只会返回void指针, 需要转化才能得到想要的对象的指针
  • C++允许重载new/delete操作符, 而malloc不允许重载, new从自由存储区上为对象动态分配内存空间, malloc从堆上分配内存

C++中有几种类型的new

  • plain new: 普通new, 特点在new和malloc区别里说了

  • nothrow new: 在空间分配失败时不会抛出异常, 而是返回NULL. 使用:

    char *p=new(nothrow) char[10e11]
    
  • new operator: 只做两件事:(1)调用operator new (2)调用类的构造函数

  • operator new: 可以重载, 实际以标准C malloc()完成

  • placement new: 在一块已经分配成功的内存上重新构造对象或对象数组. 不会出现内存分配失败, 因为他只调用构造函数而不会分配内存. 用placement new构造和对象数组, 要显式调用它们的析构函数来销毁, 而不要用delete[], 因为构造起来的对象或数组大小不一定等于原来内存的大小, 用delete会造成内存泄漏或运行时出现错误. 使用:

    #include 
    #include 
    using namespace std;
    class ADT{
        int i;
        int j;
    public:
        ADT(){
            i = 10;
            j = 100;
            cout << "ADT construct i=" << i << "j="<

你可能感兴趣的:(c++,面试,编程语言)