C++面试题

我的疑问

  1. header中防御式声明的目的
  • 防止两个头文件相互include时的循环include
  • 防止cpp在include不同头文件时可能产生的重复定义
  1. inline

将函数声明为inline可以避免函数调用的开销,空间换时间

常规的函数调用需要用到栈,需要返回地址和参数压栈,但通过inline展开后就为普通的顺序执行

与define的区别

  • define无类型检查,inline有
  • define编写时运算符的优先级较难处理
  • define在预处理时展开,inline由编译器实现展开
  1. const

const对象的值创建后值不能再改变,所以必须初始化

对于const指针,分为:

  • 底层const:int* const p = &a无法改变p的指向
  • 顶层const:const int* p = &a无法通过p改变a的值

对于const引用,其原来就不能改变引用的变量,所以只有底层constconst int& a = 1

顶层const拷贝不受限制

底层const拷贝时,右值必须为非常量或者为底层const变量

对于const成员函数,无法改变成员变量的值

  1. Static
  • 用于修饰变量:在函数内部,static 修饰的变量具有静态存储期,意味着它们的生命周期与程序的生命周期相同,而不是与函数的调用次数相关。在全局或命名空间作用域中,static 修饰的变量具有内部链接,只能在当前文件或当前命名空间中访问。

  • 用于修饰函数:在函数内部,static 修饰的函数具有内部链接,只能在当前文件中调用,不能被其他文件调用。

  • 用于修饰类成员变量:在类中,static 修饰的成员变量是类共享的,即所有类对象共享同一份内存。这些变量可以被类的任何成员函数访问,甚至在没有类对象的情况下也可以访问。需要注意的是,静态成员变量必须在类外进行定义和初始化。

  • 用于修饰类成员函数:在类中,static 修饰的成员函数是类相关的,而不是对象相关的。这意味着它们不需要通过类对象来调用,可以直接通过类名来调用。

  1. 调用构造函数和析构函数,内存的影响
  2. 内存对齐

分配内存时,按照一些规则对内存地址调整,不使用一些内存,通过空间换时间,优化访存效率

对于基础数据类型,按照4,8,16B等对齐

对于结构体和类,按照最宽基本数据类型为对齐单元

可以通过sizeof()查看