40 道高频 C++ 面试、笔试题及答案

1. 什么是多态?
答案: 多态允许对象在运行时表现出不同的行为,具体取决于其类型。

2. 虚函数和纯虚函数之间的区别是什么?
答案: 虚函数可以被派生类重写,而纯虚函数必须被派生类实现,否则派生类将成为抽象类。

3. 指针和引用的区别是什么?
答案: 指针存储变量的地址,而引用是变量的别名。引用必须初始化,而指针可以为 null。

4. 解释 C++ 中的内存管理。
答案: C++ 使用动态内存分配和释放,由 new 和 delete 运算符管理。

5. 什么是智能指针?
答案: 智能指针是自动管理内存的指针,例如 unique_ptr、shared_ptr 和 weak_ptr。

6. 解释 C++ 中的构造函数和析构函数。
答案: 构造函数在创建对象时被调用,析构函数在对象被销毁时被调用。

7. 什么是类的继承?
答案: 继承允许一个类(派生类)从另一个类(基类)继承数据成员和方法。

8. 解释 C++ 中的重载和重写。
答案: 重载允许具有相同名称但不同参数的多个函数,而重写允许派生类中的函数覆盖基类中的同名函数。

9. 什么是模板?
答案: 模板允许创建通用的代码,该代码可以在编译时根据不同类型进行实例化。

10. 解释 C++ 中的异常处理。
答案: 异常处理允许程序处理运行时错误,使用 try、catch 和 throw 关键字。

11. 什么是标准模板库 (STL)?
答案: STL 是一个提供容器、算法和迭代器的库。

12. 解释 C++ 中的流操作符。
答案: 流操作符(<< 和 >>)用于从流(例如文件或控制台)读取和写入数据。

13. 什么是 lambda 表达式?
答案: Lambda 表达式是匿名函数,可以捕获局部变量。

14. 解释 C++ 中的移动语义。
答案: 移动语义允许在不进行复制的情况下移动对象,从而提高效率。

15. 什么是 RTTI?
答案: RTTI(运行时类型信息)允许程序在运行时确定对象的类型。

16. 解释 C++ 中的友元。
答案: 友元是允许非成员函数访问私有或受保护成员的函数或类。

17. 什么是静态成员?
答案: 静态成员属于类而不是特定对象,并且在整个程序中共享。

18. 解释 C++ 中的析构函数顺序。
答案: 析构函数按相反的构造函数顺序调用。

19. 什么是虚继承?
答案: 虚继承允许派生类仅继承基类的指针,从而避免菱形继承问题。

20. 解释 C++ 中的内存对齐。
答案: 内存对齐确保对象在内存中存储在特定边界上,以提高性能。

21. 什么是位域?
答案: 位域允许将多个相关位打包到一个数据类型中。

22. 解释 C++ 中的枚举。
答案: 枚举是一种用户定义的数据类型,表示一组命名常量。

23. 什么是类型转换?
答案: 类型转换将一个数据类型转换为另一个数据类型。

24. 解释 C++ 中的预处理器宏。
答案: 预处理器宏允许在编译时执行文本替换。

25. 什么是编译期多态?
答案: 编译期多态允许在编译时确定函数或方法调用的行为。

26. 解释 C++ 中的虚基类。
答案: 虚基类允许派生类避免菱形继承问题,并确保只有一个基类的副本存储在派生类对象中。

27. 什么是多继承?
答案: 多继承允许一个类从多个基类继承。

28. 解释 C++ 中的异常规范。
答案: 异常规范允许函数指定它可能抛出的异常类型。

29. 什么是模板特化?
答案: 模板特化允许为特定类型提供模板的特定实现。

30. 解释 C++ 中的内存泄漏。
答案: 内存泄漏是指不再使用的内存未被释放,导致程序使用越来越多的内存。

31. 实现一个链表

cpp 复制代码
struct Node {
  int data;
  Node* next;
};

class LinkedList {
public:
  LinkedList();
  ~LinkedList();
  void insert(int data);
  void delete(int data);
  bool search(int data);
  int size();
private:
  Node* head;
  Node* tail;
};

32. 实现一个栈

cpp 复制代码
class Stack {
public:
  Stack();
  ~Stack();
  void push(int data);
  int pop();
  bool empty();
  int size();
private:
  vector<int> elements;
};

33. 实现一个队列

cpp 复制代码
class Queue {
public:
  Queue();
  ~Queue();
  void enqueue(int data);
  int dequeue();
  bool empty();
  int size();
private:
  vector<int> elements;
};

34. 实现一个二叉树

cpp 复制代码
struct Node {
  int data;
  Node* left;
  Node* right;
};

class BinaryTree {
public:
  BinaryTree();
  ~BinaryTree();
  void insert(int data);
  void delete(int data);
  bool search(int data);
  int size();
private:
  Node* root;
};

35. 实现一个哈希表

cpp 复制代码
class HashTable {
public:
  HashTable(int size);
  ~HashTable();
  void insert(int key, int value);
  int get(int key);
  bool contains(int key);
private:
  vector<pair<int, int>> elements;
};

36. 实现一个排序算法(如快速排序、归并排序)

cpp 复制代码
void quickSort(int* arr, int low, int high) {
  if (low < high) {
    int pivot = partition(arr, low, high);
    quickSort(arr, low, pivot - 1);
    quickSort(arr, pivot + 1, high);
  }
}

int partition(int* arr, int low, int high) {
  int pivot = arr[high];
  int i = low - 1;
  for (int j = low; j < high; j++) {
    if (arr[j] <= pivot) {
      i++;
      swap(arr[i], arr[j]);
    }
  }
  swap(arr[i + 1], arr[high]);
  return i + 1;
}

37. 实现一个字符串匹配算法(如 KMP 算法)

cpp 复制代码
void kmp(string text, string pattern) {
  int n = text.length();
  int m = pattern.length();
  vector<int> lps(m);
  computeLPS(pattern, lps);
  int i = 0;
  int j = 0;
  while (i < n) {
    if (pattern[j] == text[i]) {
      i++;
      j++;
    }
    if (j == m) {
      cout << "Pattern found at index " << i - j << endl;
      j = lps[j - 1];
    } else if (i < n && pattern[j] != text[i]) {
      if (j != 0) {
        j = lps[j - 1];
      } else {
        i++;
      }
    }
  }
}

void computeLPS(string pattern, vector<int>& lps) {
  int m = pattern.length();
  lps[0] = 0;
  int len = 0;
  int i = 1;
  while (i < m) {
    if (pattern[i] == pattern[len]) {
      len++;
      lps[i] = len;
      i++;
    } else {
      if (len != 0) {
        len = lps[len - 1];
      } else {
        lps[i] = 0;
        i++;
      }
    }
  }
}

38. 实现一个图的遍历算法(如 DFS、BFS)

cpp 复制代码
void dfs(Graph& graph, int start) {
  stack<int> s;
  s.push(start);
  while (!s.empty()) {
    int v = s.top();
    s.pop();
    if (!graph.visited[v]) {
      graph.visited[v] = true;
      cout << v << " ";
      for (int u : graph.adj[v]) {
        if (!graph.visited[u]) {
          s.push(u);
        }
      }
    }
  }
}

void bfs(Graph& graph, int start) {
  queue<int> q;
  q.push(start);
  while (!q.empty()) {
    int v = q.front();
    q.pop();
    if (!graph.visited[v]) {
      graph.visited[v] = true;
      cout << v << " ";
      for (int u : graph.adj[v]) {
        if (!graph.visited[u]) {
          q.push(u);
        }
      }
    }
  }
}

39. 实现一个动态规划算法(如背包问题)

cpp 复制代码
int knapsack(int W, int wt[], int val[], int n) {
  int dp[n + 1][W + 1];
  for (int i = 0; i <= n; i++) {
    for (int j = 0; j <= W; j++) {
      if (i == 0 || j == 0) {
        dp[i][j] = 0;
      } else if (wt[i - 1] <= j) {
        dp[i][j] = max(val[i - 1] + dp[i - 1][j - wt[i - 1]], dp[i - 1][j]);
      } else {
        dp[i][j] = dp[i - 1][j];
      }
    }
  }
  return dp[n][W];
}

40. 实现一个贪心算法(如最小生成树)

cpp 复制代码
class Edge {
public:
  int src;
  int dest;
  int weight;
};

class Graph {
public:
  vector<Edge> edges;
  int V;
  int E;
};

Graph* createGraph(int V, int E) {
  Graph* graph = new Graph();
  graph->V = V;
  graph->E = E;
  return graph;
}

void addEdge(Graph* graph, int src, int dest, int weight) {
  Edge edge;
  edge.src = src;
  edge.dest = dest;
  edge.weight = weight;
  graph->edges.push_back(edge);
}

int find(int parent[], int i) {
  if (parent[i] == -1) {
    return i;
  }
  return find(parent, parent[i]);
}

void union(int parent[], int x, int y) {
  int xset = find(parent, x);
  int yset = find(parent, y);
  parent[xset] = yset;
}

int kruskalMST(Graph* graph) {
  int V = graph->V;
  int E = graph->E;
  int parent[V];
  for (int i = 0; i < V; i++) {
    parent[i] = -1;
  }
  int mstWeight = 0;
  sort(graph->edges.begin(), graph->edges.end(), [](Edge a, Edge b) { return a.weight < b.weight; });
  for (int i = 0; i < E; i++) {
    Edge edge = graph->edges[i];
    int x = find(parent, edge.src);
    int y = find(parent, edge.dest);
    if (x != y) {
      mstWeight += edge.weight;
      union(parent, x, y);
    }
  }
  return mstWeight;
}
相关推荐
孞㐑¥8 分钟前
Linux之Socket 编程 UDP
linux·服务器·c++·经验分享·笔记·网络协议·udp
Alfred king3 小时前
面试150 生命游戏
leetcode·游戏·面试·数组
水木兰亭3 小时前
数据结构之——树及树的存储
数据结构·c++·学习·算法
CoderCodingNo4 小时前
【GESP】C++四级考试大纲知识点梳理, (7) 排序算法基本概念
开发语言·c++·排序算法
一只叫煤球的猫5 小时前
手撕@Transactional!别再问事务为什么失效了!Spring-tx源码全面解析!
后端·spring·面试
秋风&萧瑟6 小时前
【C++】C++中的友元函数和友元类
c++
梁诚斌6 小时前
使用OpenSSL接口读取pem编码格式文件中的证书
开发语言·c++
海的诗篇_7 小时前
前端开发面试题总结-原生小程序部分
前端·javascript·面试·小程序·vue·html
胡清波9 小时前
# vue 的 Diff 算法
前端·面试
Jackson_Mseven9 小时前
面试官:useEffect 为什么总背刺?我:闭包、ref 和依赖数组的三角恋
前端·react.js·面试