【C++】面试题整理
文章目录
- 一、概述
- 二、C++基础
- 2.1 - 指针在 32 位和 64 位系统中的长度
- 2.2 - 数组和指针
- 2.3 - 结构体对齐补齐
- 2.4 - 头文件包含
- 2.5 - 堆和栈的区别
- 2.6 - 宏函数比较两个数值的大小
- 2.7 - 冒泡排序
- 2.8 - 菱形继承的内存布局
- 三、智能指针
- 3.1 - 智能指针是线程安全的吗?
- 3.2 - 线程安全的几种方法
- 四、 STL
- 4.1 - map 删除
- 五、参考
一、概述
最近面试,感觉有些比较基础的好久不用就有些生疏了,整理一下。
【备注】:题目的答案是个人整理的不能保证是标准答案。
二、C++基础
2.1 - 指针在 32 位和 64 位系统中的长度
4 字节和 8 字节
32/8 = 4
64/8 = 8
2.2 - 数组和指针
以下代码在 32 位和 64 位系统中分别打印什么?
char a[] = "123456789";
const char* b = "123456789";
std::cout << sizeof(a) << std::endl;
std::cout << sizeof(b) << std::endl;
- 32位打印: 10 和 4
- 64位打印: 10 和 8
指针已经在第一题中说过了,就不重复了。char 数组的大小需要加上最后的 \0
。
2.3 - 结构体对齐补齐
在 32 位和 64 位系统中分别是多少
struct M
{int a;double b;
};printf("%d", sizeof(struct M));
答案: 均为16,这里是结构体的对齐补齐,与系统位数无关。
2.4 - 头文件包含
两种包含头文件的区别
#include <stdio.h>
#include "stdio.h"
- 尖括号,编译器会从系统目录中查找;
- 双引号,编译器会首先从当前项目目录查找,找不到再去系统目录中查找。
虽然#include"“的查找范围更广,但是这并不意味着,不论是系统头文件,还是自定义头文件,一律用#include”“包含。因为#include”"的查找顺序存在先后关系,如果项目当前目录或者引用目录下存在和系统目录下重名的头文件,那么编译器在当前目录或者引用目录查找成功后,将不会继续查找,所以存在头文件覆盖的问题。另外,对于系统头文件,用#include<>包含,查找时一步到位,程序编译时的效率也会相对更高。
2.5 - 堆和栈的区别
- 堆(heap): 向上增长内存,存储动态分配的内存,需要程序员自己管理,分配和释放。
- 栈(stack): 向下增长内存,存储静态分配的内存,系统会自动释放。
2.6 - 宏函数比较两个数值的大小
要求不使用大于、小于和if
#define MAX(a,b) (int)((a)/(b)) == 0 ? (a) : (b);
定义宏函数需要注意,入参需要使用小括号括起来,避免传入算式导致预期外的计算
MAX(4-1,5);
// 不加小括号 4 - 1/5 = 3 返回3 值错误。
// 加小括号 (4-1)/(5) = 0, 返回值为 5。
2.7 - 冒泡排序
void bubbleSort(int arr*, int n)
{for (int i = 0; i < n - 1; ++i){for (int j = 0; j < n - i - 1; ++j){if (arr[j] > arr[j+1]){int tmp = arr[j];arr[j] = arr[j+1];arr[j+1] = arr[j];}}}
}
如果我是面试官,我会在这里考一个打印 arr 的 sizeof ,因为 数组在传参时会退化为指针。
2.8 - 菱形继承的内存布局
网上找到一个讲的很好的 在这里
https://blog.csdn.net/AgoniAngel/article/details/105893798
三、智能指针
3.1 - 智能指针是线程安全的吗?
不是,虽然引用计数是原子操作,但还有其他的操作
3.2 - 线程安全的几种方法
- 加锁
- 原子变量
std::atomic
四、 STL
4.1 - map 删除
改错。
using std::map;
using std::string;
int main(int argc, char* argv[])
{map<string, string> mapData;mapData["a"] = "aaa"; mapData["b"] = "bbb"; mapData["c"] = "ccc"; for (map<string, string>::iterator i=mapData.begin(); i!=mapData.end(); i++){if (i->first == "b"){mapData.erase(i);}}return 0;
}
错误是容器删除元素会有迭代器失效,网上给的改错方式是,将for循环 i++
删除 加到函数中
for (map<string, string>::iterator i=mapData.begin(); i!=mapData.end(); /*i++*/)
{if (i->first == "b"){mapData.erase(i++);}else{i++;}
}
个人感觉这样也可以
for (map<string, string>::iterator i=mapData.begin(); i!=mapData.end();)
{if (i->first == "b"){i = mapData.erase(i);}else{++i;}
}
五、参考
- https://blog.csdn.net/rammuschow/article/details/107947302
- https://en.cppreference.com/w/cpp/container/map/erase