面试学习笔记(2)——C++工程师

C++工程师面试学习笔记

  • 基础知识
    • static关键字
    • C和C++的区别
    • C++中的四种cast转换
    • 指针和引用的区别
    • 野指针
    • 智能指针
    • 智能指针内存泄漏
    • 为什么析构函数必须是虚函数,但默认析构函数不是虚函数
    • fork函数
    • strcpy和strlen
    • map和set
    • STL的组成
    • C++内存管理

这篇博客主要记录一些C++常考题目以及必要知识。

基础知识

static关键字

  1. 全局静态变量:
    存储位置:静态存储区
    生命周期:整个程序运行期间
    初始化:0
    作用域:从定义开始到文件结尾
  2. 局部静态变量:
    存储位置:静态存储区
    生命周期:整个程序运行期间
    初始化:0
    作用域:局部作用域,离开作用域不销毁
  3. 静态函数:
    作用域:仅本文件可见,不会与其他文件中的同名函数冲突
  4. 类的静态成员:
    静态成员可以实现多个对象之间的数据共享,还不会破坏隐藏的原则。
    对于多个对象,静态数据成员只储存一份,供所有对象使用。
  5. 类的静态函数:
    与静态成员类似,都不是对象成员,因此引用不需要对象名。
    静态成员函数实现不能直接引用非静态成员,必须通过对象来引用。(因为静态成员函数先编译,这时其他非静态成员还未创建)

C和C++的区别

  1. 设计思想:C++面向对象,C面向过程。
  2. 语法:C++具有封装、继承、多态,增加了许多类型安全的功能,支持范式编程,如模版类,函数模版等。

C++中的四种cast转换

  1. const_cast:用于将const变量转成非const。
  2. static_cast:用于各种隐式转换,如非const转const,void*转指针等,并且能用于多态中向上转化,向下转化也可以,但是不安全。
  3. dynamic_cast:用于动态类型转化/只能用于含有虚函数的类,用于类层次间的向上和向下转换。只能转指针或引用。
    向上转换指的是子类向基类的转化,向下转换指的是基类向子类的转换。因此向下转换时可能会出现非法情况,返回NULL。
  4. reinterpret_cast:可能会有问题,少用。

指针和引用的区别

  1. 指针有自己的空间,而引用只是一种别名。
  2. 指针本质上是一个地址,大小是地址长度,引用大小是被引对象的大小。
  3. 指针可以初始化为NULL,引用必须是已有对象的引用。
  4. 参数传递时,指针需要被解引用才可以对对象进行操作(即从相应地址中取出对象)。
  5. 有const指针,没有const引用。
  6. 指针可以变指向,引用不能。
  7. 指针可以有多级,引用最多只能一级。
  8. 指针操作和引用操作含义不同。
  9. 动态内存分配必须用指针,否则会引起内存泄漏。

野指针

指的是指向一个已经删除对象或未申请访问受限内存区域的指针。

智能指针

用于管理在堆上分配的内存,将普通的指针封装为栈对象,当该对象生存周期结束后,会在析构函数中释放申请的内存,从而防止内存泄漏。

智能指针内存泄漏

对shared_ptr这一智能指针,它使用引用计数的方式进行记录,只有引用记录为0时才会自动释放内存,但是当两个对象相互使用一个shared_ptr成员变量指向对方时,会造成循环引用,使得引用计数失效,导致内存泄漏。
为了解决这个问题,引入了weak_ptr弱指针,weak_ptr的构造函数不会修改引用技术值,但是可以检测对象是否释放,从而避免非法访问。

为什么析构函数必须是虚函数,但默认析构函数不是虚函数

将析构函数设置为虚函数可以保证当我们new一个子类时,可以通过基类的指针指向该子类对象,通过释放基类指针释放子类空间,防止内存泄漏。
默认析构函数不是虚函数是因为虚函数需要额外的虚函数表和虚表指针,占用额外的内存,对于不会被继承的类,会浪费内存。

fork函数

fork函数会创建一个新的进程,与父进程一摸一样,并且都会继续运行。子进程fork会返回0,父进程则返回子进程的进程id,如果出现错误则返回负值。

strcpy和strlen

strcpy是字符串拷贝函数,拷贝遇到‘\0’结束,没有长度限制,可能会拷贝越界,安全版本是strncpy函数。
strlen是计算字符串长度的函数,返回开始到‘\0’之间的字符个数。

map和set

map和set都是C++的关联容器,底层都使用红黑树来实现。
unordered_map底层是用哈希表实现的。
map中的元素是key-value键值对,通过key值做为索引,set中的元素就是关键字的简单集合。
set的迭代器是const的,不允许修改元素,map的迭代器允许修改value但是不允许修改key。因为map使用key,set使用关键字来排序保证其有序性的,如果修改key,需要重新调节平衡,会破坏结构。
map支持下标操作,set不支持,但最好用find解决问题。

STL的组成

  1. 容器
  2. 迭代器
  3. 仿函数
  4. 算法
  5. 分配器
  6. 配接器
    分配器给容器分配空间,算法通过迭代器获取内容,仿函数协助算法完成操作,配接器用来套接适配仿函数。

C++内存管理

  1. 代码段:只读存储区和文本区,只读存储区存储字符串常量,文本区存储程序的机器代码。
  2. 数据段:存储程序中已初始化的全局变量和静态变量。
  3. bss段:存储未初始化的全局+静态变量,以及所有初始化为0的 全局+静态变量。
  4. 堆区:new/malloc动态分配内存,同时需要delete/free来手动释放申请的内存。
  5. 映射区:存储动态链接库以及调用mmap函数进行的文件映射。
  6. 栈区:存储函数的返回地址,参数,局部变量和返回值。

你可能感兴趣的:(面试学习记录,c++)