39 |
--------------------------------------------------------------------------------
/C++面经汇总/微软 - C++ 工程师面经汇总.md:
--------------------------------------------------------------------------------
1 | # 微软 - C++ 工程师面经汇总
2 |
3 | :date: 2020-10-20
4 |
5 | ## 语言
6 | - 虚函数的机制
7 | - buffer 拷贝的过程
8 | - 一般程序中栈大小多少
9 | - 栈和堆的区别,如何分配内存
10 | - extern 关键字的底层机制是怎么实现的
11 | - 静态绑定和动态绑定是怎么实现的
12 | - 虚函数表跟对象还是跟类绑定
13 | - 返回函数中的静态变量的地址会发生什么
14 | - 全局 static 变量和非 static 的有什么区别
15 | - 全局变量定义在头文件中有什么问题
16 | - memcpy 函数常用吗?怎么实现?怎么提高效率
17 | - copy-on-write 是什么?你用过吗
18 | - C++ 并发编程了解吗?一般怎么写
19 | - 讲 C++ 对象模型,多态怎么实现,虚函数对象存储结构
20 | - delete 怎么知道要删除多长的
21 | - unordered_map 怎么实现的?画一下底层的数据结构
22 | - sorted_set 怎么实现
23 | - volatile 关键字
24 | - .h 里面定义函数,会在什么阶段错误?为什么 .h 里面一般只放函数声明?为什么这么设计
25 | - C++ 模板做什么的?
26 | - 静态链接、动态链接
27 | - C++ 和 Java/Python 区别
28 |
29 |
30 | ## 计算机网络
31 | - TCP 三次握手
32 | - TCP 握手为什么需要三次
33 | - TCP 四次挥手最后 client 端的状态是什么
34 | - TIMEWAIT 是什么作用?为什么要等这个时间?等多长时间? MSL 是多长时间
35 | - http 和 https 有什么区别
36 | - TCP 和 UDP 区别
37 | - 抓取数据包得过程
38 | - NAT 转换怎么实现的
39 |
40 |
41 | ## 数据库
42 | - 各种 join 的区别
43 | - 数据库引擎熟悉吗?原理
44 | - 用过什么数据库
45 | - 数据库的索引能讲下吗?怎么设计的
46 | - ACID 解释下
47 | - 数据库范式都有哪些
48 |
49 |
50 | ## 操作系统
51 | - 进程和线程的区别
52 | - 线程有哪几种状态,相互关系得转化图
53 | - 多线程的好处
54 | - 假如我有一个 exe,这个 exe 是根据一个 cpp文件得到的,cpp 文件里面有一个 main 函数,main 里面有一句 print 函数,main 函数之前会有一些变量,说一下从我的鼠标点击运行开始到这个 main 的 return 之后的全部过程
55 | - 什么是静态链接库和动态链接库
56 | - 什么是内核
57 | - 死锁发生的条件
58 | - 生产者消费者 PV 操作伪代码
59 | - Linux 启动的过程
60 | - BootLoader 做了什么
61 | - Linux 进程默认占用多少内存
62 | - 怎么用 C++ 读取进程的内存占用情况
63 | - Linux 进程通信都有哪些方式
64 | - IO 多路复用,select,poll,epoll 的区别
65 | - 多线程编程常用吗?一个经典的生产者消费者模型怎么实现?怎么降低锁的竞争?
66 | - 虚拟内存映射怎么做的
67 | - 内存碎片怎么整理?用什么数据结构?
68 | - 为什么要有虚拟内存?4gb数据在2gb内存排序?有虚存能直接排吗
69 | - 中断机制
70 |
71 |
72 | ## 算法
73 | - 打乱数组
74 | - 链表深拷贝,可能有环,可能无环
75 | - 缺失数字
76 | - 把数字翻译成字符串
77 | - 验证IP地址
78 | - 最小k个数
79 | - 反转链表
80 | - 数据流中的中位数
81 | - LRU缓存
82 | - 合并二叉树
83 | - 二分查找
84 | - 快速排序得实现原理,非递归方式怎么实现
85 | - 合并k个升序链表
86 | - 二叉树的最大路径和
87 | - 括号生成
88 | - 删除二叉搜索树中的节点
89 | - 数组中重复的数
90 | - 大数加法
91 | - 删除链表倒数第k个节点
92 | - 旋转数组
93 | - 数组中的逆序对
94 | - 最大子序和
95 | - 按Z字型顺序打印二叉树
96 | - 格雷编码
97 | - 重建二叉树
98 | - 最长上升序列
99 | - 二叉树的最大路径和
100 |
101 | ## 其他
102 | - 英文自我介绍
103 | - 假设我现在要设计一个扫雷程序,你觉得你要怎么设计?就是假如你要设计类要设计几个,分别有什么功能
104 | - 你比较看重公司的哪些性质
105 | - 你的强项和弱项
106 | - 你希望在公司1-3年有什么收获
107 | - 随便说一分钟英语
108 | - 介绍一下你曾经遇到的难题和解决过程
109 |
110 | ## 总结
111 | - 外企看重算法,也看重综合素质和潜力。
112 | - 很少直接考 CS 基础,但细节暴露一切。
113 |
114 |
--------------------------------------------------------------------------------
/EffectiveCPP/C++ explicit关键字详解.md:
--------------------------------------------------------------------------------
1 | # C++ explicit关键字详解
2 |
3 | 首先, C++中的explicit关键字只能用于修饰只有一个参数的类构造函数, 它的作用是表明该构造函数是显示的, 而非隐式的, 跟它相对应的另一个关键字是implicit, 意思是隐藏的, 类构造函数默认情况下即声明为implicit(隐式).
4 |
5 | 那么显示声明的构造函数和隐式声明的有什么区别呢? 我们来看下面的例子:
6 |
7 | ```cpp
8 | class CxString // 没有使用explicit关键字的类声明, 即默认为隐式声明
9 | {
10 | public:
11 | char *_pstr;
12 | int _size;
13 | CxString(int size)
14 | {
15 | _size = size; // string的预设大小
16 | _pstr = (char*) malloc(size + 1); // 分配string的内存
17 | memset(_pstr, 0, size + 1);
18 | }
19 | CxString(const char *p)
20 | {
21 | int size = strlen(p);
22 | _pstr = malloc(size + 1); // 分配string的内存
23 | strcpy(_pstr, p); // 复制字符串
24 | _size = strlen(_pstr);
25 | }
26 | // 析构函数这里不讨论, 省略...
27 | };
28 |
29 | // 下面是调用:
30 |
31 | CxString string1(24); // 这样是OK的, 为CxString预分配24字节的大小的内存
32 | CxString string2 = 10; // 这样是OK的, 为CxString预分配10字节的大小的内存
33 | CxString string3; // 这样是不行的, 因为没有默认构造函数, 错误为: “CxString”: 没有合适的默认构造函数可用
34 | CxString string4("aaaa"); // 这样是OK的
35 | CxString string5 = "bbb"; // 这样也是OK的, 调用的是CxString(const char *p)
36 | CxString string6 = 'c'; // 这样也是OK的, 其实调用的是CxString(int size), 且size等于'c'的ascii码
37 | string1 = 2; // 这样也是OK的, 为CxString预分配2字节的大小的内存
38 | string2 = 3; // 这样也是OK的, 为CxString预分配3字节的大小的内存
39 | string3 = string1; // 这样也是OK的, 至少编译是没问题的, 但是如果析构函数里用free释放_pstr内存指针的时候可能会报错, 完整的代码必须重载运算符"=", 并在其中处理内存释放
40 |
41 | ```
42 |
43 | 上面的代码中, ``"CxString string2 = 10;"`` 这句为什么是可以的呢? 在C++中, 如果的构造函数只有一个参数时, 那么在编译的时候就会有一个缺省的转换操作:将该构造函数对应数据类型的数据转换为该类对象. 也就是说 ``"CxString string2 = 10;"`` 这段代码, 编译器自动将整型转换为CxString类对象, 实际上等同于下面的操作:
44 |
45 | ```cpp
46 | CxString string2(10);
47 | 或
48 | CxString temp(10);
49 | CxString string2 = temp;
50 | ```
51 |
52 | 但是, 上面的代码中的_size代表的是字符串内存分配的大小, 那么调用的第二句 ``"CxString string2 = 10;"`` 和第六句 ``"CxString string6 = 'c';"`` 就显得不伦不类, 而且容易让人疑惑. 有什么办法阻止这种用法呢? 答案就是使用explicit关键字. 我们把上面的代码修改一下, 如下:
53 |
54 | ```
55 | class CxString // 使用关键字explicit的类声明, 显示转换
56 | {
57 | public:
58 | char *_pstr;
59 | int _size;
60 | explicit CxString(int size)
61 | {
62 | _size = size;
63 | // 代码同上, 省略...
64 | }
65 | CxString(const char *p)
66 | {
67 | // 代码同上, 省略...
68 | }
69 | };
70 |
71 | // 下面是调用:
72 |
73 | CxString string1(24); // 这样是OK的
74 | CxString string2 = 10; // 这样是不行的, 因为explicit关键字取消了隐式转换
75 | CxString string3; // 这样是不行的, 因为没有默认构造函数
76 | CxString string4("aaaa"); // 这样是OK的
77 | CxString string5 = "bbb"; // 这样也是OK的, 调用的是CxString(const char *p)
78 | CxString string6 = 'c'; // 这样是不行的, 其实调用的是CxString(int size), 且size等于'c'的ascii码, 但explicit关键字取消了隐式转换
79 | string1 = 2; // 这样也是不行的, 因为取消了隐式转换
80 | string2 = 3; // 这样也是不行的, 因为取消了隐式转换
81 | string3 = string1; // 这样也是不行的, 因为取消了隐式转换, 除非类实现操作符"="的重载
82 | ```
83 |
84 | **explicit关键字的作用就是防止类构造函数的隐式自动转换.**
85 |
86 | 上面也已经说过了, **explicit关键字只对有一个参数的类构造函数有效**, 如果类构造函数参数大于或等于两个时, 是不会产生隐式转换的, 所以explicit关键字也就无效了. 例如:
87 |
88 | ```cpp
89 | class CxString // explicit关键字在类构造函数参数大于或等于两个时无效
90 | {
91 | public:
92 | char *_pstr;
93 | int _age;
94 | int _size;
95 | explicit CxString(int age, int size)
96 | {
97 | _age = age;
98 | _size = size;
99 | // 代码同上, 省略...
100 | }
101 | CxString(const char *p)
102 | {
103 | // 代码同上, 省略...
104 | }
105 | };
106 |
107 | // 这个时候有没有explicit关键字都是一样的
108 | ```
109 |
110 |
111 | 但是, 也有一个例外, 就是**当除了第一个参数以外的其他参数都有默认值的时候, explicit关键字依然有效**, 此时, 当调用构造函数时只传入一个参数, 等效于只有一个参数的类构造函数, 例子如下:
112 |
113 | ```cpp
114 | class CxString // 使用关键字explicit声明
115 | {
116 | public:
117 | int _age;
118 | int _size;
119 | explicit CxString(int age, int size = 0)
120 | {
121 | _age = age;
122 | _size = size;
123 | // 代码同上, 省略...
124 | }
125 | CxString(const char *p)
126 | {
127 | // 代码同上, 省略...
128 | }
129 | };
130 |
131 | // 下面是调用:
132 |
133 | CxString string1(24); // 这样是OK的
134 | CxString string2 = 10; // 这样是不行的, 因为explicit关键字取消了隐式转换
135 | CxString string3; // 这样是不行的, 因为没有默认构造函数
136 | string1 = 2; // 这样也是不行的, 因为取消了隐式转换
137 | string2 = 3; // 这样也是不行的, 因为取消了隐式转换
138 | string3 = string1; // 这样也是不行的, 因为取消了隐式转换, 除非类实现操作符"="的重载
139 | ```
140 |
141 | ## 小结
142 |
143 | - explicit关键字的作用就是防止类构造函数的隐式自动转换
144 | - explicit关键字只对有一个参数的类构造函数有效
145 | - 当除了第一个参数以外的其他参数都有默认值的时候, explicit关键字依然有效
146 |
--------------------------------------------------------------------------------
/EffectiveCPP/using的用法.md:
--------------------------------------------------------------------------------
1 | # using的用法
2 |
3 | ## 1、概述
4 | 我们用到的库函数基本上都属于命名空间std的,在程序使用的过程中要显示的将这一点标示出来,如std::cout。这个方法比较烦琐,而我们都知道使用using声明则更方便更安全。
5 |
6 | 这个我们程序员肯定都知道了,今天突发奇想就想对using整理一下。
7 |
8 | ## 2、命令空间的using声明
9 | 我们在书写模块功能时,为了防止命名冲突会对模块取命名空间,这样子在使用时就需要指定是哪个命名空间,使用using声明,则后面使用就无须前缀了。例如:
10 |
11 | ```
12 | using std::cin; //using声明,当我们使用cin时,从命名空间std中获取它
13 | int main()
14 | {
15 | int i;
16 | cin >> i; //正确:cin和std::cin含义相同
17 | cout << i; //错误:没有对应的using声明,必须使用完整的名字
18 | return 0;
19 | }
20 | ```
21 |
22 | ```cpp
23 | //main.cpp
24 |
25 | #include | 37 | | 38 |
39 | ```./*.sh```
40 | ``sh ./*.sh`` 41 | ``bash ./*.sh`` 42 | |
43 |
44 | ``source ./*.sh``
45 | ``. ./*.sh`` 46 | |
47 |
| 50 | 是否需要执行权限 51 | | 52 |53 | 只有`./*.sh`需要权限 54 | | 55 |56 | 否 57 | | 58 |
| 61 | 是否创建子shell 62 | | 63 |64 | 是,变量不与父shell环境交互 65 | | 66 |67 | 否, 变量与父shell环境交互 68 | | 69 |
3 |
| 对象类型 | 42 |对象 | 43 |操作类型 | 44 |
|---|---|---|
| 数据库模式 | 47 |模式 | 48 |CREATE SCHEMA |
49 |
| 基本表 | 52 |CREATE SCHEMA,ALTER TABLE |
53 | |
| 视图 | 56 |CREATE VIEW |
57 | |
| 索引 | 60 |CREATE INDEX |
61 | |
| 数据 | 64 |基本表和视图 | 65 |SELECT,INSERT,UPDATE,DELETE,REFERENCES,ALL PRIVILEGES |
66 |
| 属性列 | 69 |SELECT,INSERT,UPDATE,REFERENCES,ALL PRIVILEGES |
70 |
40 | High frequent interview LeetCode test for FaceBook, Linkedin, Amazon, Google. More importantly, the problems' solutions are provided in C/C++, Python and Java. Offer, Offer, Offer ! 41 |
42 | 48 |