C++大厂面试真题宝典 精选100道(完结)

qwas125 · · 50 次点击 · · 开始浏览    

 

获课:weiranit.fun/6100/

获取ZY↑↑方打开链接↑↑

以下是一些C++ 大厂面试真题12:

基础语法

  1. C++ 与 C 的区别

  • C 是面向过程的语言,C++ 是面向对象的语言,C++ 还支持泛型编程和函数式编程等特性。

  • C++ 支持动态内存管理new/delete,C 使用malloc/free

  • C++ 支持函数重载、引用等特性,C 不支持。

  • 指针与引用的区别

  • 指针是一个变量,存储的是另一个变量的地址,可以通过*操作符来访问指针所指向的变量,指针可以为空,也可以重新赋值指向其他变量。

  • 引用是一个变量的别名,在定义时必须初始化,并且一旦初始化后就不能再引用其他变量,对引用的操作实际上就是对被引用变量的操作。

  • const关键字的作用

  • 定义常量,使变量的值不可修改。

  • 修饰函数参数,表明函数不会修改传入的参数值。

  • 修饰函数的返回值,限制返回值不能被修改。

  • 修饰类的成员函数,表明该成员函数不会修改对象的成员变量。

面向对象编程

  1. 多态的实现方式

  • 函数重载:在同一个类中,允许存在多个同名函数,但函数的参数列表不同(参数个数、参数类型或参数顺序不同)。编译器会根据调用函数时传入的参数来决定调用哪个函数,这是一种静态多态,在编译时就确定了调用的函数。

  • 虚函数:在基类中使用virtual关键字声明的函数,子类可以重写该函数。当通过基类指针或引用调用虚函数时,会根据对象的实际类型来决定调用哪个类的虚函数,这是一种动态多态,在运行时才确定调用的函数。

  • 抽象类与接口类的区别

  • 抽象类可以包含普通成员变量和成员函数,也可以包含纯虚函数,抽象类不能被实例化,只能作为基类被继承。

  • 接口类通常只包含纯虚函数和静态常量,没有普通成员变量和非纯虚函数,接口类的目的是为了定义一组相关的操作,让子类去实现这些操作。

  • 构造函数和析构函数的作用及调用时机

  • 构造函数用于初始化对象的成员变量,在对象创建时自动调用,可以有多个构造函数,实现构造函数的重载。

  • 析构函数用于释放对象占用的资源,在对象销毁时自动调用,每个类只能有一个析构函数。

模板与 STL

  1. 模板的概念及使用场景

  • 模板是 C++ 中实现泛型编程的一种机制,它允许程序员编写与类型无关的代码,提高了代码的复用性。

  • 常用于容器类(如vectorlistmap等)、算法库(如sortfind等)的实现,以及编写通用的函数和类,适用于需要处理多种数据类型,但逻辑相同的场景。

  • mapunordered_map的区别

  • map内部是基于红黑树实现的,元素是有序的,按照键的大小进行排序,查找、插入和删除操作的时间复杂度为。

  • unordered_map内部是基于哈希表实现的,元素是无序的,查找、插入和删除操作的平均时间复杂度为,但在最坏情况下可能退化。

数据结构与算法

  1. 如何在 C++ 中实现一个栈

  • 可以使用数组或链表来实现栈。使用数组实现时,需要定义一个数组和一个栈顶指针,通过栈顶指针来操作栈的元素。使用链表实现时,需要定义一个链表节点结构体,通过链表的头指针来操作栈的元素,入栈操作在链表头部插入节点,出栈操作删除链表头部节点。

  • 描述二叉树的遍历方式及其实现

  • 前序遍历:先访问根节点,再递归地前序遍历左子树,最后递归地前序遍历右子树。

  • 中序遍历:先递归地中序遍历左子树,再访问根节点,最后递归地中序遍历右子树。

  • 后序遍历:先递归地后序遍历左子树,再递归地后序遍历右子树,最后访问根节点。

并发编程

  1. C++11 引入了哪些多线程特性

  • std::thread类:用于创建和管理线程,方便地启动一个新线程来执行指定的函数。

  • std::mutex类:互斥锁,用于保护共享资源,确保在同一时刻只有一个线程能够访问共享资源,防止数据竞争和并发错误。

  • std::condition_variable类:条件变量,用于线程间的同步,允许线程在满足特定条件时等待或唤醒其他线程。

  • 原子操作:std::atomic模板类提供了对原子类型的支持,用于实现无锁编程,保证对共享变量的原子访问,避免使用锁带来的性能开销。

  • 如何避免死锁

  • 资源有序分配:对资源进行编号,规定线程只能按照从小到大的顺序获取资源,避免循环等待资源的情况。

  • 避免资源独占:尽量减少对资源的独占时间,在使用完资源后及时释放,以便其他线程能够获取资源。

  • 资源预分配:在程序开始时,一次性分配所有需要的资源,避免在运行过程中动态分配资源导致的死锁。

  • 以下是继续为你补充的 C++ 大厂面试真题:

基础语法

  1. newmalloc的区别

  • new是 C++ 中的操作符,malloc是 C 语言中的函数。

  • new在申请内存时会调用构造函数来初始化对象,malloc只是分配内存空间,不会进行初始化。

  • new返回的是对象类型的指针,malloc返回的是void*类型的指针,需要进行类型转换。

  • new可以进行重载,malloc不能。

  • static关键字的作用

  • 修饰全局变量时,使全局变量的作用域仅限于当前文件,其他文件无法访问。

  • 修饰局部变量时,局部变量在程序运行期间只初始化一次,下次进入函数时,会保留上一次的值。

  • 修饰类的成员变量时,该成员变量为类的所有对象所共享,不属于任何一个具体的对象。

  • 修饰类的成员函数时,该成员函数只能访问类的静态成员变量,不能访问非静态成员变量。

面向对象编程

  1. 多重继承和虚继承的区别

  • 多重继承是一个类可以从多个基类继承,可能会导致菱形继承问题,即一个派生类从两个或多个基类继承,而这些基类又从同一个基类继承,会导致数据冗余和二义性。

  • 虚继承是为了解决多重继承中的菱形继承问题,在继承时使用virtual关键字,使得在派生类中只保留一份共同基类的成员,避免数据冗余和二义性。

  • 什么是纯虚函数和抽象类

  • 纯虚函数是在基类中声明的虚函数,它在基类中没有实现,只是给出了函数的原型,在派生类中必须实现。

  • 包含纯虚函数的类称为抽象类,抽象类不能被实例化,只能作为基类被继承,用于定义一组相关的操作,让子类去实现这些操作。

模板与 STL

  1. 实现一个简单的模板函数

收起

cpp

template <typename T>T add(T a, T b) {    return a + b;}
  1. vectorlist的区别

  • vector基于动态数组实现,支持随机访问,访问元素的时间复杂度为,在尾部插入和删除元素的时间复杂度为,在中间插入和删除元素的时间复杂度为。

  • list基于双向链表实现,不支持随机访问,访问元素的时间复杂度为,在任何位置插入和删除元素的时间复杂度为。

数据结构与算法

  1. 实现一个二叉搜索树的插入操作

收起

cpp

// 二叉树节点结构体struct TreeNode {    int val;    TreeNode* left;    TreeNode* right;    TreeNode(int x) : val(x), left(NULL), right(NULL) {}};// 插入操作TreeNode* insertIntoBST(TreeNode* root, int val) {    if (root == NULL) {        return new TreeNode(val);    }    if (val < root->val) {        root->left = insertIntoBST(root->left, val);    } else {        root->right = insertIntoBST(root->right, val);    }    return root;}
  1. 写一个函数实现字符串的反转

收起

cpp

#include <iostream>#include <cstring>void reverseString(char* str) {    int len = strlen(str);    for (int i = 0; i < len / 2; i++) {        char temp = str[i];        str[i] = str[len - i - 1];        str[len - i - 1] = temp;    }}int main() {    char str[] = "hello world";    reverseString(str);    std::cout << str << std::endl;    return 0;}

并发编程

  1. std::unique_lockstd::lock_guard的区别

  • std::lock_guard是一个简单的 RAII(Resource Acquisition Is Initialization)锁包装器,在构造函数中获取锁,在析构函数中释放锁,不能手动释放锁,也不能在获取锁后进行其他操作。

  • std::unique_lockstd::lock_guard更灵活,它可以在构造函数中不获取锁,而是在需要的时候手动获取锁,也可以手动释放锁,还可以进行锁的转移等操作。

  • 什么是条件变量,如何使用

  • 条件变量是 C++ 中用于线程间同步的机制,它允许线程在满足特定条件时等待或唤醒其他线程。

  • 使用时,通常需要与互斥锁配合使用,一个线程在获取互斥锁后,检查条件是否满足,如果不满足,则调用条件变量的wait函数等待,此时线程会释放互斥锁并进入等待状态,直到其他线程满足条件后调用条件变量的notify_onenotify_all函数唤醒等待的线程,等待的线程被唤醒后会重新获取互斥锁,然后继续执行。

50 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传