[编程开发] 学C++,是越学越觉得C++好用,还是越学越觉得C++很扯淡?

[复制链接]
fj520 发表于 2023-10-3 19:23:58|来自:福建 | 显示全部楼层 |阅读模式
学C++,是越学越觉得C++好用,还是越学越觉得C++很扯淡?
全部回复5 显示全部楼层
twinsbbs 发表于 2023-10-3 19:24:32|来自:福建 | 显示全部楼层
当然是越用越好用。
我从学c++开始到现在是超过20年,工作上是用了十几年,从最初的c++98用到现在的c++20,C++的进化原则之一就是易用性。标准委员会甚至还成立了一个专门的教学组,用来研究C++教程的简化(虽然目前没任何成果,但是态度上是值得肯定的),也有一些成果例如import std就是对新手最大的妥协。
C++的社区非常分裂,各种理由都会导致相互的鄙视链,比如说C with Class流派就经常被开除C++籍,有时候哪怕只是命名规范的不同也会吵起来,更不用说要不要用多重继承的争论了。
我早期对这种氛围非常反感,后来心态发生了变化,我觉得分裂是繁荣的必然结果。如果是一个非常小众的语言,相互之间的包容性会非常高,因为大家会珍惜来之不易的交流机会。而C++的社区非常庞大繁荣,根本不需要多包容彼此便可以找到和自己志同道合的人。
我现在也认为,C++根本不存在最佳实践,无论什么风格、什么用法,自己的团队统一起来就好,以解决实际问题为目标。C with Class也并不比面向对象和纯魔板方式low,能解决问题就行,不要自己鄙视自己。不同的行业对C++的使用习惯也非常不同,各种C++交流会的视频(youtube上很多),可以看到不同的行业是如何使用C++的,对自己不了解的行业的C++用法要抱着学习的态度而不要抱着挑刺的态度。
这些年国内的C++岗位其实是一直在增涨的 ,我在其它的回答里面有提到过一些,未来几年汽车行业应该会新增不少C++需求。
peterll 发表于 2023-10-3 19:25:12|来自:福建 | 显示全部楼层
1)学c++,是越学越觉得好用。自己最早的一批代码都是c语言写的,后来用了c++以后,觉得class 太好用了,写面向对象的编程太人性化了,太符合人的思维方式了,代码太好扩展了,真的太棒了。
1.1) 最早用C语言写代码的时候,写到1万行以后就很困难了,来回翻找,太多函数和全局变量了,记不准啊,写代码的效率和速度比1000行的时候,慢了很多很多。
1.2) 有了C++ class, 只需要记住几个 class name 就可以了,然后加上后来IDE的智能化程度也高,自动补齐之类的,太棒了,真的太好了,写代码的效率也大大提高了,所有的代码都归类到几个class中了,函数接口少了很多,只需要关注public的几个函数了,其它函数都是private, 不需要记忆和关注,瞬间感觉代码的控制力从1万行扩展到10万行了,关注的层次大大提高了,关注点大大减少了。
2)开始大规模的使用C++ std库和boost库,大量的现成轮子可以用,代码的开发效率继续提升。
3)C++ std库的缺陷。
3.1) 早期C++ std::string一直有bug,一直到gcc 5.x以后才彻底稳定下来,最简单最常用库,修了很多年的bug才全部修完,太让人失望了,特别简单的bug,是COW的问题,造成了很多问题,就这样一直拖着, 很多年也不修,直到所有其它的知名库都要先写一套string,std::string不可靠的恶名传遍整个C++er,到gcc 5.x以后才修复完此bug。
3.2) 有一次发现backtrace指向shared_ptr相关,后来发现是库bug,那个boost shared_ptr的count计数初值的赋值过程竟然是普通赋值,谁能想到,初始化期间既没有使用内存屏障fence, 也没有使用原子量atomic,简单的多线程bug。C++17 删除了unique() 这个函数 , 只是消灭了表面的bug,  库里面这个bug依旧存在。这是多线程的最常用基础库,不能不用。
有哪些BUG是看起来很简单,但是处理起来极其麻烦的?4)大规模造轮子。
4.1) 重写各种C/C++基础库了,自己动手丰衣足食,写了shared_ptr,  也陆续把所有的用过的C++组件全部写完了。全部常用库 vector deque unorered_map map string 等都是重写一遍后,发现性能均大幅度提升,打破了对C++ std库的幻想,发现了新世界的大门,就是大多数库代码都不是最优解,一些库存在稳定性问题。
4.2) 最近写的是内存库,大约有一个数量级的提升,并且碎片更少和稳定性更好。glibc malloc函数存在的问题是:包括缺页中断瞬间闪崩的小概率问题,严重的内存碎片问题,性能过低,直接跨线程复用内存导致多线程lockfree ABA的问题和其它影响多线程稳定性的问题。通过自己写自研内存库这些已经全部解决了。
4.3) 曾经有崩溃后 backtrace 追踪到 glibc memset。使用自研 memcpy 和 memset 之后,codeblocks 在启动的最初阶段(启用多线程之前)的小概率崩溃问题,也消失了。对于大型软件,出现小概率情况也非常普遍,这也是为什么 oracle 数据库内部版本测试跑一个月的原因,设法找到小概率bug。

5)C++er 太不容易了,面对的 Linux 开发环境中 底层小概率问题太多了。
5.1) 有一部分多线程的小概率bug,在其它存在gc的语言中不会发生,完全不是C++er的问题,是内存库的问题,glibc malloc函数存在直接跨线程复用内存导致多线程lockfree ABA的问题和其它复用影响多线程稳定性的问题,不是C++代码的问题,根源就在glibc malloc在太短的时间内跨线程复用了这些使用过的空间,这在其它存在gc的语言中不会发生。gc都是过很久才回收一次,并且回收本身的消耗时间也大,没有这个问题。自研内存库解决了这个问题。
5.2) memcpy memset 非对齐事件造成的小概率bug,在其它解释语言中不会发生。因为对于C++由于函数的调用非常快,而且乱序执行,一旦出现非对齐场景下特殊冲突,很容易出现未定义事件,例如AVX 非对齐写入指令后,后续指令中有针对同一物理空间的普通数据读写,那么这个地方就有概率出现指令级并发冲突,因为这两部分虽然是针对同一空间,但是地址是不同的(不对齐啊),CPU识别不了是同一地址的先后依赖关系。这些特殊点是未定义事件点,需要额外的关注,进行特殊处理,而这些在其它解释性语言中不会发生,因为语言慢啊,中间不知道多少个时钟周期了,才会有读写,已经是两个独立读写事件了,不会冲突了。自研memcpy库解决了这个问题。
5.3) 有一部分多线程的小概率bug,只使用 C++ std::mutex 是无法解决的。同样的场景,解释语言由于语言执行很慢并发量上不去,小概率问题难触发,情况要好的多。Java语言由于偏向锁的设计,更倾向于上次的线程加锁(更稳定,对cpu同步要求低),以及语言自身执行慢一些并发量更低一些,情况也要远好于C++。
5.3.1)Paul E.Mckenney解决多线程bug的思路:他一个人修复了Linux内核的1000多处多线程bug,都是用RCU的无锁方式重写代码解决的,不仅性能高,稳定性也高,是这个世界上最懂多线程的人之一。我自己也写了这么多年的多线程代码,不认为使用 mutex 可以满足稳定性的全部要求,那只是一个幻觉,只要并发量起来了,迟早会遇到无法解决的小概率问题。
5.3.2) 多线程的高稳定性并发方案: 推荐 RCU模式,per_thread 模式 和 per_cpu 模式也不错,wait_free 模式( 有适配最终一致性的代码 ),自研 spin_lock ( 有偏向锁的设计(类似java思路),有适配最终一致性的代码 )。这几种方式都对CPU同步有更低的要求(即使假如,某款CPU的某种原因导致相关数据某种场景下出现数据经过较长时间才同步到各CPU也不会有问题,能够适应CPU之间出现短期不一致和最终一致,对CPU的fence指令和atomic指令的前后内存的对外的顺序性也不做严格要求,只要求经过足够长的时间后CPU之间数据能够达成最终一致 ),  因此非常可靠健壮,性能也非常高。
5.3.3) 不信任 教材上的那种几行源码的spin_lock可靠,不信任 开源的一两百行的 lock_free 和 wait_free 可靠。很多理想化的 代码太短的 开源并发工具包 均存在小概率bug。
5.4) linux 环境下大量使用内存时,会偶发小概率缺页中断瞬间闪崩。glibc ptmalloc库存在此问题,大型软件或者消耗内存比较多的程序会遇到此小概率bug。在程序启动阶段,大型应用软件偶然会触发此小概率bug,导致启动中断,重新执行一次又能正常进入。程序进入时闪崩的小概率问题,一大部分原因是内存库的小概率bug,很多都不是C++er的程序的问题。C++er会比其它语言有更多概率遇到此类小概率bug。自研内存库使用malloc返回默认已经分配物理内存指针的方案来解决此问题,这样用户的应用程序就不会发生缺页中断了,提升了性能和稳定性。使用hugepage可以减少缺页中断次数512倍,也能大幅度减少此类崩溃事件的发生,同时有更高的性能表现。自研内存库默认支持hugepage。
6 ) C++er 进阶路上的劫数。
由于代码执行速度快,c++ 更容易引发第5条的一些底层小概率bug,尤其是经常写出更快代码的老司机,代码速度越快,遇到底层小概率bug的机会也越多,或许写慢几倍几十倍就遇不到了。上面写的第5条的相关条款,均是性能高手的大杀劫,也是进阶路上的绊脚石,也是一部分老司机的最终劫数所在。C++er 新手的代码更慢更稳定呢。
6.1) 使用SSE/AVX指令的小概率bug。老司机经常使用SSE/AVX指令,参见5.2,如果没有足够的经验,很容易掉进小概率bug的坑里。实际上还有一些SSE/AVX对齐指令也容易触发类似小概率问题,但概率要远好于SSE/AVX非对齐指令,intel cpu前后指令的依赖关系是一个非常复杂的话题,这里不讨论,懂的人少。一部分程序员没有能力解决此类问题,unknow unknow。
6.2) mm fence / pause 内存屏障 / 空闲指令等对时序有特殊要求的指令使用上的坑。老司机经常会开发高性能的并发程序,获得更高的性能表现,但是如果没有足够的经验,即使直接复制粘贴业内大佬论文中的没有问题的一模一样的并发代码,也可能掉坑里。原因是: 他们调用封装后的 inline fence函数, 硬件fence 和几条时序特殊要求的指令 例如 mm pause 空闲指令等 在工程上需要封装 compiler barrier 空函数 保护,在这些指令的前后必须要有 compiler barrie 空函数 的保护,就是告诉编译器,这几条指令的顺序千万别改啊,千万别把此指令前后的顺序弄乱,千万别优化。一旦程序员缺乏编译器知识,或者不小心,没有使用 compiler barrier 拦着编译器优化,后果就不可预测。( gcc  compiler_barrier()  的一个例子:  #define   compiler_barrier()    __asm__ volatile ("" ::: "memory") 。
。。。
迈天过海 发表于 2023-10-3 19:26:02|来自:福建 | 显示全部楼层
越学越觉得C++很扯淡!
很多人越学越没自信,真不是谣言,是真的会这样!C++究竟难在哪里?
C++难就难在:在C++中你找不到任何一件简单的事。
知友自我嘲笑C++经典语录:
1个月: 都说C++难,但聪明如我,一个月就读完了C++ primer,我看这C++也不过如此.
3个月: 原来之前一直在用C++语法写C... 开始正式学习C++...
1年: 今天花一下午一定要琢磨明白这段代码啥意思...
2年: C++太他妈难了, 发明C++的可以吃X去了
3年: 这辈子绝对不能继续搞C++了,珍惜生命,远离C++
4年: ......
5年: 终于神功初成, 大家好,我是C++专家,疑难杂症请问我
7年: 我比较擅长XXX这块,其他方面我是外行
10年: 我有一定的C++基础...
对于多数初学者来说,C++ 的难度并不在语法语意等语言层面,而是没学过 C++ 所支持的面向对象、泛型编程、元编程、函数式编程等不同编程范式,以至于标准模板库(STL)里关于数据结构和算法的知识,甚至一些部分与计算机架构、编译原理、操作系统等知识相关。学习 C++ 可以同时学习、实践这些相关知识。
有人把C++和物理作类比。我很同意。理论物理是一场无尽的旅程,总有最前沿的东西。我对神经科学很感兴趣,也有幸与一个神经科学相关专业的学生交流过,她还给我发过资料,我很感激。然而我在知乎上看到过一个相关的讨论。一个人说“我小时候就想知道大脑是如何工作的,于是我学了神经科学,如今我已经是神经科学博士,依然不知道大脑是如何工作的”。所以我的求知欲只能暂且到此为止。C++亦是如此。
扯远了,我们来说C++有多难吧。
我们只谈构造函数。假如我们有一个类Teacher。
  1. class Teacher
  2. {
  3. private:
  4.     std::string name;
  5.     std::string position;
  6. };
复制代码
我们考虑给Teacher类加上构造函数。
  1. class Teacher
  2. {
  3. private:
  4.     std::string name;
  5.     std::string position;
  6. public:
  7.     Teacher(const std::string& n, const std::string& p)
  8.         : name(n), position(p) {}
  9. };
复制代码
虽然语义正确,但是如果我们的实参只为了传递给Teacher,传递之后而没有其他作用的话,那么这个实现是效率低下的。字符串的拷贝花销可观(关于std::string的COW,SSO,view的讨论是另一个故事了)。我们在C++11里面有右值引用move语义,所以呢,我们可以改成这样。
  1. class Teacher
  2. {
  3. private:
  4.     std::string name;
  5.     std::string position;
  6. public:
  7.     Teacher(const std::string& n, const std::string& p)
  8.         : name(n), position(p) {}
  9.     Teacher(std::string&& n, std::string&& p)
  10.         : name(std::move(n)), position(std::move(p)) {};
  11. };
复制代码
你可能觉得这样也已经不错了。不过我们还有可能第一个参数右值,第二个参数左值。或者第一个参数左值,第二个参数右值。所以实际上我们需要四个函数的重载。
  1. class Teacher
  2. {
  3. private:
  4.     std::string name;
  5.     std::string position;
  6. public:
  7.     Teacher(const std::string& n, const std::string& p)
  8.         : name(n), position(p) {}
  9.     Teacher(std::string&& n, std::string&& p)
  10.         : name(std::move(n)), position(std::move(p)) {};
  11.     Teacher(const std::string&& n, const std::string& p)
  12.         : name(std::move(n)), position(p) {}
  13.     Teacher(const std::string& n, const std::string&& p)
  14.         : name(n), position(std::move(p)) {}
  15. };
复制代码
代码有点多。我们有没有什么方法写一个通用的函数来实现这四个函数呢?有。我们在C++11中有完美转发
  1. class Teacher
  2. {
  3. private:
  4.     std::string name;
  5.     std::string position;
  6. public:
  7.     template <typename S1, typename S2>
  8.     Teacher(S1&& n, S2&& p)
  9.         : name(std::forward<S1>(n)), position(std::forward<S2>(p)) {};
  10. };
复制代码
完成了。美滋滋。然而事情没有这么简单。如果我们的position有默认值,然后我们写如下代码的话。
  1. class Teacher
  2. {
  3. private:
  4.     std::string name;
  5.     std::string position;
  6. public:
  7.     template <typename S1, typename S2 = std::string>
  8.     Teacher(S1&& n, S2&& p = "lecturer")
  9.         : name(std::forward<S1>(n)), position(std::forward<S2>(p)) {};
  10. };
  11. int main()
  12. {
  13.     Teacher t1 = { "david", "assistant" };
  14.     Teacher t2{ t1 };
  15. }
复制代码
我们出现了编译期错误。因为Teacher t2{ t1 };的重载决议的最佳匹配是我们的模板,而不是默认的拷贝构造函数,因为拷贝构造函数要求t1是const的。所以,我们可能需要SFINAEtype traits来修改我们的代码。注意,默认函数参数不能类型推导,所以我们才需要的S2的默认模板参数。
  1. class Teacher
  2. {
  3. private:
  4.     std::string name;
  5.     std::string position;
  6. public:
  7.     template <typename S1, typename S2 = std::string,
  8.     typename = std::enable_if_t<!std::is_same_v<S1, Teacher>>>
  9.     Teacher(S1&& n, S2&& p = "lecturer")
  10.         : name(std::forward<S1>(n)), position(std::forward<S2>(p)) {};
  11. };
复制代码
仍然不对哦,因为我们的完美转发有引用折叠机制,我们应该判断的S1是Teacher&而不是Teacher。其次,如果有类继承我们的Teacher的话,拷贝的时候依然会出现这个问题,所以我们需要的不是is_same而是is_convertible。然而,如果我们直接写std::is_convertible_v<S1, Teacher>的话,我们实际上判定是不是可以转换的时候,还是会去看我们的构造函数。也就是说我们自己依赖了自己,无穷递归。所以我们需要的是std::is_convertible_v<S1, std::string>。所以,我们修改我们的代码。
  1. class Teacher
  2. {
  3. private:
  4.     std::string name;
  5.     std::string position;
  6. public:
  7.     template <typename S1, typename S2 = std::string,
  8.     typename = std::enable_if_t<std::is_convertible_v<S1, std::string>>>
  9.     Teacher(S1&& n, S2&& p = "lecturer")
  10.         : name(std::forward<S1>(n)), position(std::forward<S2>(p)) {};
  11. };
复制代码
其次,因为我们的默认参数是字面量,字面量是const char[]类型的。我们调用构造函数的时候,也会用字面量。字面量不是std::string类型会造成很多问题。然而在C++14中,我们可以用User-defined literals来把字面量声明成std::string类型的。不过记得命名空间,这个名字空间不在std中。我们这里不再讨论了。
我们接下来讨论用构造函数初始化的问题。初始化有很多种写法,以下我列出有限的几种。
  1. Teacher t1("david"s);
  2. Teacher t2 = Teacher("david"s);
  3. Teacher t3{ "lily"s };
  4. Teacher t4 = { "lily"s };
  5. Teacher t5 = Teacher{ "lily"s };
  6. auto t6 = Teacher("david"s);
  7. auto t7 = Teacher{ "lily"s };
复制代码
我们用了auto。然而auto是decay的。而decltype(auto)不。所以,以下代码如果用auto的话可能不是你需要的。
  1. const Teacher& t8 = t1;
  2. auto t10 = t8;
复制代码
我们需要写const auto&。
此外,我们可以看出,用小括号和大括号好像没什么区别。不过,在一些情况下会有很大的差别。我们列出一些。
  1. std::vector<int> vec1(30, 5); std::vector<int> vec2{ 30, 5 };
复制代码
甚至因为C++17的构造函数自动推导,我们可以写出更加疯狂的代码。
  1. std::vector vec3{ vec1.begin(), vec2.end() };
复制代码
这个代码是用初始化列表初始化的,也就是说我们得到的vec3中有两个iterator。
好了,我们回过头来说auto。我们可以看到好像我们所有的初始化都可以用auto。是这样吗?如果我们写atomic的代码呢?
  1. auto x = std::atomic<int>{ 10 };
复制代码
是可以的。因为在C++17中我们有Copy Elision。所以这里没有拷贝函数的调用,和直接定义并初始化是一致的。但是atomic初始化是有问题的。
  1. std::atomic<int> x{};
复制代码
这样是不能零初始化的。当然了,这显然是API的不一致,或者说错误。所以我们有LWG issue 2334。预计在C++20修复这个问题。嘻嘻。
以上内容基于《C++ templates》的作者Nicolai Josuttis的几场talk。
作者:琉璃
链接:https://www.zhihu.com/question/30196513/answer/563560938
来源:知乎
这里详细谈下C++ 的学习路线,按照这个路线去学习C++,每个阶段都帮你规划好了学习时间,只要你努力且认真的去学了, 保证帮你既高效又扎实的学好C++:

一、C++基础(3个月)

1、面向对象的三大特性:封装、继承、多态
2、类的访问权限:private、protected、public
3、类的构造函数、析构函数、赋值函数、拷贝函数
4、移动构造函数与拷贝构造函数对比
5、深拷贝与浅拷贝的区别
6、空类有哪些函数?空类的大小?
7、内存分区:全局区、堆区、栈区、常量区、代码区
8、C++与C的区别
9、struct与class的区别
10、struct内存对齐
11、new/delete与malloc/free的区别
12、内存泄露的情况
13、sizeof与strlen对比
14、指针与引用的区别
15、野指针产生与避免
16、多态:动态多态、静态多态
17、虚函数实现动态多态的原理、虚函数与纯虚函数的区别
18、继承时,父类的析构函数是否为虚函数?构造函数能不能为虚函数?为什么?
19、静态多态:重写、重载、模板
20、static关键字:修饰局部变量、全局变量、类中成员变量、类中成员函数
21、const关键字:修饰变量、指针、类对象、类中成员函数
22、extern关键字:修饰全局变量
23、volatile关键字:避免编译器指令优化
24、四种类型转换:static_cast、dynamic_cast、const_cast、reinterpret_cast
25、右值引用
26、std::move函数
27、四种智能指针及底层实现:auto_ptr、unique_ptr、shared_ptr、weak_ptr
28、shared_ptr中的循环引用怎么解决?(weak_ptr)
29、vector与list比较
30、vector迭代器失效的情况
31、map与unordered_map对比
32、set与unordered_set对比
33、STL容器空间配置器
参考书籍:《C++ Primer》(第5版)、《STL源码剖析》、《深度探索C++对象模型》
下载地址:

  • 链接:https://pan.baidu.com/s/1qqAR6iqjur1sfmzeZjcrwg
  • 提取码:m6gx
  • 戳下面获取面试真题:
大厂15万字C++开发面试手册出炉(C++和计算机基础全有)​mp.weixin.qq.com/s?__biz=MzU4MjgwNjQ0OQ==&mid=2247487041&idx=1&sn=1c49fe6e12b1e52f66462b8b942e1644&chksm=fdb3f09fcac47989e399f52a975a6d2b18bd15e8cdfe720e3d878866f2d05c758318e2f6241f#rd​mp.weixin.qq.com/s?__biz=MzU4MjgwNjQ0OQ==&mid=2247487041&idx=1&sn=1c49fe6e12b1e52f66462b8b942e1644&chksm=fdb3f09fcac47989e399f52a975a6d2b18bd15e8cdfe720e3d878866f2d05c758318e2f6241f#rd二、计算机网络(1个月)

1、OSI7层网络模型:应用层、表示层、会话层、运输层、网络层、链路层、物理层
2、TCP/IP四层网络模型:应用层、运输层、网际层、接口层
综合OSI与TCP/IP模型,学习五层网络模型:
从上向下架构:应用层、运输层、网络层、链路层、物理层
链路层:
3、MTU
4、MAC地址
网络层:
5、地址解析协议
6、为啥有IP地址还需要MAC地址?同理,为啥有了MAC地址还需要IP地址?
7、网络层转发数据报的流程
8、子网划分、子网掩码
9、网络控制报文协议ICMP
10、ICMP应用举例:PING、traceroute
运输层:
11、TCP与UDP的区别及应用场景
12、TCP首部报文格式(SYN、ACK、FIN、RST必须知道)
13、TCP滑动窗口原理
14、TCP超时重传时间选择
15、TCP流程控制
16、TCP拥塞控制(一定要弄清楚与流量控制的区别)
17、TCP三次握手及状态变化。为啥不是两次握手?
18、TCP四次挥手及状态变化。为啥不是三次挥手?
19、TCP连接释放中TIME_WAIT状态的作用
20、SYN泛洪攻击。如何解决?
21、TCP粘包
22、TCP心跳包
23、路由器与交换机的区别
24、UDP如何实现可靠传输
应用层:
25、DNS域名系统。采用TCP还是UDP协议?为什么?
26、FTP协议(了解)
27、HTTP请求报文与响应报文首部结构
28、HTTP1.0、HTTP1.1、HTTP2.0对比
29、HTTP与HTTPS对比
30、HTTPS加密流程
31、方法:GET、HEAD、POST、PUT、DELETE
32、状态码:1、2、3、4、5**
33、cookie与session区别
34、输入一个URL到显示页面的流程(越详细越好,搞明白这个,网络这块就差不多了)
参考书籍:《计算机网络》(第5版)、《TCP/IP详解卷1:协议》、《图解HTTP》
下载地址:

  • 链接:https://pan.baidu.com/s/1fRYNn3E0yEOLiQUSyBlxKg
  • 提取码:69dc
三、操作系统(1个月)

1、进程与线程区别
2、线程同步的方式:互斥锁、自旋锁、读写锁、条件变量
3、互斥锁与自旋锁的底层区别
4、孤儿进程与僵尸进程
5、死锁及避免
6、多线程与多进程比较
7、进程间通信:PIPE、FIFO、消息队列、信号量、共享内存、socket
8、管道与消息队列对比
9、fork进程的底层:读时共享,写时复制
10、线程上下文切换的流程
11、进程上下文切换的流程
12、进程的调度算法
13、阻塞IO与非阻塞IO
14、同步与异步的概念
15、静态链接与动态链接的过程
16、虚拟内存概念(非常重要)
17、MMU地址翻译的具体流程
18、缺页处理过程
19、缺页置换算法:最久未使用算法、先进先出算法、最佳置换算法
ps:操作系统的内容看起来不是很多,实际上每个问题答案的底层原理要弄懂还是很考验基本功的。比如:互斥锁与自旋锁的区别,实际上涉及到阻塞时线程的状态是不一样的。互斥锁阻塞的线程是挂起的,此时系统会优先执行其它可执行的线程,就会将阻塞的线程切换到可执行线程,而当临界区执行的时间非常短时,此时线程切换频繁、开销较大,此时就会采用自旋锁的方式,让阻塞的线程处于忙等状态。

参考书籍:《深入理解计算机系统》
下载地址:

  • 链接:https://pan.baidu.com/s/1RoDN317X-C6izxY6CwuxTA
  • 提取码:iy8u

四、网络编程(1个月)

1、IO多路复用:select、poll、epoll的区别(非常重要,几乎必问,回答得越底层越好,要会使用)
2、手撕一个最简单的server端服务器(socket、bind、listen、accept这四个API一定要非常熟练)
3、线程池
4、基于事件驱动的reactor模式
5、边沿触发与水平触发的区别
6、非阻塞IO与阻塞IO区别
参考书籍:《Unix网络编程》
ps:网络编程掌握以上几点就够了,要搞明白还是要花很久时间的。
下载地址:

  • 链接:https://pan.baidu.com/s/1MD9WAAmSOCz5fhlUMU0bsg
  • 密码:bwyt

五、数据结构与算法及刷题(2个月)

1、数组
2、链表
3、栈
4、队列
5、堆
6、二叉树:二叉搜索树、平衡树、红黑树
7、B树、B+树
8、哈希表及哈希冲突
9、排序算法:冒泡排序、简单选择排序、插入排序、希尔排序、归并排序、堆排序、快速排序
(要求能够面试时手写出堆排序和快速排序)
10、二分法:旋转数组找target
11、回溯法:全排列、复原IP地址
12、动态规划(掌握基本的动态规划的几个题其实就够了,如:斐波那契数列、接雨水、股票的最佳买入时机)
参考书籍:《图解算法》《剑指offer》
ps:建议刷题与数据结构算法同时进行,这样理解得更深入。刷题网站leetcode,刷完《剑指offer》其实就能解决大部分面试手撕了。
书籍下载:

  • 链接:https://pan.baidu.com/s/1GZEp8KI1Fm0U4Uek7BOWAw
  • 提取码:am4o
六、mySQL数据库(7天~15天)

1、数据存储引擎:InnoDB、myISAM、Memory
2、数据库索引类型及原理:B+树索引、哈希表索引
3、锁:悲观锁、乐观锁
4、事务:事务的四大特性(ACID)、事务并发的三大问题、事务隔离级别及实现原理
5、多版本并发控制实现机制(MCVV)原理
参考书籍:《高性能MySQL》
ps:这里也可以参考本人写的博客:mysql知识点总结。
下载地址:

  • 链接:https://pan.baidu.com/s/1-_9Cwq1qCxAr041nDWe0sg
  • 提取码:fy0y
七、项目(2个月)

如果时间够的话就可以写一个项目,当然大部分人写的项目都是一个烂大街的项目,也就是“web高性能服务器”。其实就是根据陈硕大神写的《Linux高性能服务器编程:使用muduo C++网络库》进行改编,当然啦,读懂这本书还是很耗时的,学习其中的思想也会受益匪浅的。
总结
按照上面推荐的内容来学习的话,要学习得深入一点的话1年的时间肯定需要的,甚至2年也不足为其。当然对于非科班的学生来说,大部分都没有充足的时间的,这时候建议尽量把C++基础、计算机网络、操作系统、网络编程、数据结构与算法这五个部分的内容学得很扎实,大概6个月的时间。
戳下面获取面试真题:
大厂15万字C++开发面试手册出炉(C++和计算机基础全有)​mp.weixin.qq.com/s?__biz=MzU4MjgwNjQ0OQ==&mid=2247487041&idx=1&sn=1c49fe6e12b1e52f66462b8b942e1644&chksm=fdb3f09fcac47989e399f52a975a6d2b18bd15e8cdfe720e3d878866f2d05c758318e2f6241f#rd​mp.weixin.qq.com/s?__biz=MzU4MjgwNjQ0OQ==&mid=2247487041&idx=1&sn=1c49fe6e12b1e52f66462b8b942e1644&chksm=fdb3f09fcac47989e399f52a975a6d2b18bd15e8cdfe720e3d878866f2d05c758318e2f6241f#rd另外想要校招进大厂的同学,东哥熬夜给大家准备了一份资料:
BAT大佬整理的进大厂必看秘籍!八、推荐阅读书单
正如侯捷老师所说C++ 相关的书籍也非常多,如天上繁星。 广博如四库全书者有 《The C++Programming Language》 《C++ Primer》,深奥如山重水复者有《The Annotated C++ Reference Manual》、《Inside The C++ Object Model》,细说历史者有《The Design And Evolution Of C++》、《Rumiations on C++》,独沽一味者有《Polymorphism in C++》、《Genericity in C++》,独树一帜者有《Design Patterns》、《C++ FAQs》,程序库大全有之《The C++ Standard Library》.....
至于书单的话,可以看下这个C++ 最全书单,包含几十本经典的PDF和下载方式:
华为最牛逼的c++ 基础与提高PDF​mp.weixin.qq.com/s?__biz=MzU4MjgwNjQ0OQ==&mid=2247486995&idx=1&sn=382ef6a0c1d20bdcc4531463024a8060&chksm=fdb3f0cdcac479dbf38c2db05f3d57ef6cb2acbd2edf977244523026a58258520a784933810b#rd​mp.weixin.qq.com/s?__biz=MzU4MjgwNjQ0OQ==&mid=2247486995&idx=1&sn=382ef6a0c1d20bdcc4531463024a8060&chksm=fdb3f0cdcac479dbf38c2db05f3d57ef6cb2acbd2edf977244523026a58258520a784933810b#rd​mp.weixin.qq.com/s?__biz=MzU4MjgwNjQ0OQ==&mid=2247486995&idx=1&sn=382ef6a0c1d20bdcc4531463024a8060&chksm=fdb3f0cdcac479dbf38c2db05f3d57ef6cb2acbd2edf977244523026a58258520a784933810b#rd​mp.weixin.qq.com/s?__biz=MzU4MjgwNjQ0OQ==&mid=2247486995&idx=1&sn=382ef6a0c1d20bdcc4531463024a8060&chksm=fdb3f0cdcac479dbf38c2db05f3d57ef6cb2acbd2edf977244523026a58258520a784933810b#rd(PS:侯捷 C++ 视频课程一直都被看过的同学广为推荐,最近发现 B 站关于侯捷老师的 C++ 视频课程几乎全部被下架了,于是自己搜集了一套非常全的视频,大家赶紧去下载保存备用:
侯捷C++全套视频|含下载方式​mp.weixin.qq.com/s?__biz=MzU4MjgwNjQ0OQ==&mid=2247486987&idx=1&sn=6002f1b0c275f97a33ee2e3e8f53ab4f&chksm=fdb3f0d5cac479c3368acf8cecbf5b0669ff76db88b3f32d3543fcd8f0f5c820845102493c16#rd​mp.weixin.qq.com/s?__biz=MzU4MjgwNjQ0OQ==&mid=2247486987&idx=1&sn=6002f1b0c275f97a33ee2e3e8f53ab4f&chksm=fdb3f0d5cac479c3368acf8cecbf5b0669ff76db88b3f32d3543fcd8f0f5c820845102493c16#rd​mp.weixin.qq.com/s?__biz=MzU4MjgwNjQ0OQ==&mid=2247486987&idx=1&sn=6002f1b0c275f97a33ee2e3e8f53ab4f&chksm=fdb3f0d5cac479c3368acf8cecbf5b0669ff76db88b3f32d3543fcd8f0f5c820845102493c16#rd​mp.weixin.qq.com/s?__biz=MzU4MjgwNjQ0OQ==&mid=2247486987&idx=1&sn=6002f1b0c275f97a33ee2e3e8f53ab4f&chksm=fdb3f0d5cac479c3368acf8cecbf5b0669ff76db88b3f32d3543fcd8f0f5c820845102493c16#rd他们让知识的传播变得更加的便捷,降低了后来者的学习门槛,当然啦也变相加重了内卷化.
最后给大家介绍一份计算机经典书籍,送大家一份硬核书籍资源:读大学跟工作期间,我买了很多书,大部分是一些技术书籍,也收集了这些书籍的电子版,都在这里,现在免费share给大家,包括了计算机类常用电子书,包括C,C++,Java,Python,Java,Linux,Go等,希望大家能认真阅读。点击下方链接直达获取:
计算机经典必读书单(含下载方式)

码字不易,硬核码字更难,希望大家不要吝啬自己的鼓励,给我 :
@码农出击
一个点赞,鼓励下我!
版版有王暴 发表于 2023-10-3 19:26:07|来自:福建 | 显示全部楼层
学C++让我想起了苏轼的一句诗:横看成岭侧成峰,远近高低各不同。不识庐山真面目,只缘身在此山中。
第一年学C++的感觉:真特么难,真扯淡,简单的东西搞这么复杂!
第二年学C++的感觉:越来越好用了,C++ YYDS!我感觉基本我都会了!
第三年学C++的感觉:卧槽,居然还有这么多复杂的东西,太扯淡了!
第四年学C++的感觉:哈哈哈,我终于成专家了,C++真特么好用。
........
第N年学C++的感觉:无底洞啊这是。。。怎么用了这么多年还感觉我自己是个初学者。。。
C++语言上限非常高,使用C++语言基本什么都能做,什么都能做好,做不到或者做不好更多认为是开发者水平问题,而不是语言问题。
但C++之后的很多语言都有局限性和特异性,这代表着它们的确解决不了某些问题。
虽然C++语言上限高,但对使用者的要求也极高,C++真的博大精深且越学越难!难的不是语言本身,而是用语言这个工具去和操作系统打交道的过程。
举个栗子:锤子简单吗?足够简单吧,但各种精美的雕塑就是用锤子一锤一锤敲出来的,这个过程难吗?非常难。其他高级语言?类似你直接用一个磨具制造机器造出雕塑,那当然简单太多
C++ 作者及委员会想给你带来足够的抽象能力,让你可以抽象这个世界;给你足够的自由与控制硬件的能力,及零开销的高性能。光是指针带来各种复杂性问题就够我们吃一壶了。
用其他高级语言,比如Java,JVM这个大管家就帮你搞定各种困难的事情了。野指针?不存在的!
C++程序员好比代码宇宙的神,新手神一不小心弄点问题出来就把代码宇宙毁灭了。而其他高级语言?程序员更像一个操作员,真正的神是JVM这种万能机器!
但是对于一部分有追求的程序员来说呢?成为代码宇宙的神,是他们的追求,但即便他们训练多少年,也不敢说自己可以完全驾驭代码宇宙。
学好C++,首先是要有需求场景,比如你是一个C++游戏引擎开发工程师、又或者是一个Linux C++后端服务工程师(公司的服务端对高可用/高并发甚至执行效率都有严苛的要求)等等。
在这个基础上,无外乎:实践中精益求精、多看C++经典书籍、多看C++开源项目。
工作中就不多说了,始终带着重构和更完美代码实现的决心即可。
毕业前,猛学C++三年,硕士毕业加入腾讯做游戏用的就是C++,随后担任过360技术委员会成员,在C++这条路上走得更远了,今天也给大家一些系统学习C++的建议:
一、C/C++入门阶段
这个阶段全力以赴的话,一年时间差不多可以掌握。
刚入门的时候我们主要是学习培养编程思维和动手能力,深刻理解面向过程和面向对象的思想方法,这对以后的程序员之路非常重要!
所以学习语言更为重要:
面向对象编程思想;类的封装,构造和析构、静态成员、对象管理;类的构造(有参构造函数、无参构造、拷贝构造、默认构造函数)和析构;对象动态管理、友元函数、友元类、操作符重载; C++编译器对象管理模型分析;类对象的动态管理(new/delete);友元函数和友元类;运算符重载(一元运算符、二元运算符、运算符重载难点、项目开发中的运算符重载);类的继承、多继承及其二义性、虚继承;多态(概念、意义、原理剖析、多态案例);虚函数、纯虚函数、抽象类(面向抽象类编程思想案例);函数模板、类模板,模板的继承。
C++类型转换;C++输入输出流(标准I/O 文件I/O 字符流I/O);C++异常处理(异常机制、异常类型、异常变量、异常层次结构、标准异常库);利用一些IDE开发工具:诸如Windows平台VC系列:VC++6.0(比较古老) ;Visual Studio2013, Visual Studio2015,Visual Studio2017,Visual Studio2019;Mac平台的XCode系列,还有CodeBlock,另附一些高级编辑器Notepad++, EditPlus,UE等一些开发工具的常用设置和一些常见快捷键的使用。
这个阶段推荐以下两本书:
《Essential C++》 这是一本内容不多但很实用的C++入门书籍,强调快速上手与理解C++编程。本书主要围绕一系列逐渐复杂的程序问题,以及用以解决这些问题的语言特性展开讲解。你不只学到C++的函数和结构,也会学习到它们的设计目的和基本原理。
《C++ Primer》 本书对C++基本概念、技术、以及现代C++编程风格进行了全面而且权威的阐述,是C++初学者的最佳指南;本书可以帮助你编写实用的程序,而无需首先精通每个语言细节。对于中高级程序员,本书也是不可或缺的参考书。
二、C/C++开发进阶
这个阶段非常刻苦的话,需要两年以上时间。
另外我把大学和工作中用的经典电子书库(包含数据结构、操作系统、C++/C、网络经典、前端编程经典、Java相关、程序员认知、职场发展)、面试找工作的资料汇总都打包放在这了,这套资源可不是一般那种网上找的资源,是伴随我从学生一路成长为腾讯高级开发工程师,360技术经理、360技术总监、中小公司CTO的打包全套,非常宝贵!点击下方链接直达获取:


我已经帮大家打包好了,点击下方链接直接获取:

计算机经典书籍
在第二阶段学习的时候,就是比较重要的了,C++开发的进阶之路,更是一个让自己找份薪水比较体面的工作的筹码。
C++进阶之STL:
STL = Standard Template Library,即标准模板库。这是提高开发效率的极品工具。通过学习此阶段,应掌握泛型编程技巧,理解容器类在C++语言中的应用模式,以及熟练掌握全部STL类的使用方法。
C++进阶之设计模式:
决定一个项目成败最重要的因素是项目总体的设计,通过本阶段的学习,可掌握面向对象编程中重要的一环,是编码前建模的技巧所在。单例模式;工厂模式;代理模式;迭代模式等,这些都是你要掌握的哦。
C++进阶之数据结构基础:
这是所有编程语言中最应该学习的部分,程序组成的基础之一。顺序存储、链式存储、循环链表;
双向链表、栈(顺序和链式)、队列(顺序和链式);
栈的应用、树基本概念及遍历、二叉树;
排序算法、并归算法、选择、插入、快速、希尔。
这个阶段推荐以下几本书:
《Effective C++》和《More effective C++》 作者是Scott Meyers。你应该熟读它们,并清楚地理解每个项目。该书围绕55条准则,每一条都介绍了一个可让你写出更好的C++程序代码的方法,并以特别设计过的例子详加讨论。
《Exceptional C++(C++编程剖析)》和《More exceptional C++》 这两本书中都包含了40个C++编程问题,这些问题会让你磨练自己的技能,最终成为优秀的C++程序员。这些问题是Herb Sutter精心挑选,与ISO/ANSI C++官方标准相一致,帮助程序员在设计、架构和编码过程中保持良好的风格,从而使编写的C++软件更健壮、更高效。
《Inside the C++ object model(深度探索C++对象模型)》 本书专注于C++面向对象程序设计的底层机制,包括结构式语意、临时性对象的生成、封装、继承,以及虚拟——虚拟函数和虚拟继承,帮助你理解程序的底层实现,以便写出更高效的代码。
《The design and evolution of C++(C++语言的设计与演化)》 本书作者也是C++语言的设计者Bjarne Stroustrup,作者在书中综合性地介绍了C++的发展历史,C++中各种重要机制的本质意义和设计背景,这些机制的基本用途和使用方法,讨论了C++所适合的应用领域及其未来的发展前景,既没有忽略关键性的详情,又没有过多地陷入技术细节。
三、C++开发高级
这个阶段几乎伴随了职场后续的整个生涯,只有更精没有最精,C++高手之路,任重道远!
C++进阶之QT开发:
掌握QT类库构架,图形界面开发模型;掌握QT开发技巧,消息机制,图形处理;掌握QT网络编程,UDP,TCP使用方式;掌握QT文件处理方式,序列化;掌握QT在windows,linux,ios,android不同平台下的移植技术
C++进阶之Windows/Linux网络服务器:
掌握Unix/Linux平台开发方式;熟练使用系统调用;熟练Unix/Linux内存管理,进程,线程调度;掌握MFC界面开发,网络编程;熟悉网络服务器开发方式,熟练编写TCP,UCP网络服务程序;掌握同步/异步IO模型在网络编程中的使用方式。
C++进阶之数据库开发:
掌握SQL语言的实用技巧。Oracle,MySQL数据库的使用方式。
如果你能熟练掌握以上列出的技能,具备解决复杂问题和技术难点的能力,而且你能独立开发一些比较复杂的功能模块,这个时候月薪过万都是小意思了!
这就是所谓的程序员大牛了,当下炙手可热的全栈开发工程师,既晓前端,又通后台。快速定位问题,解决问题对他们来说已是小菜一碟,就是人们常说的神秘大牛,只在公司技术攻关的时候才会才看到他们的身影。
这个阶段,在C++领域,你已经飞跃愚昧之巅跨越绝望之谷,进入开悟之破了。推荐以下书籍:
《The C++ standard library(C++标准程序库)》 这是标准模板库字典,你可以在本书中找到STL相关的一切知识。本书焦点放在标准模板库、检查容器、迭代器、函数对象和STL算法上。每一个元素都有深刻的呈现,包括其介绍、设计、运用实例、细节解说、陷阱、意想不到的危险,以及相关类别和函数等。
《Effective STL》 这是Scott Meyers的第三本C++专著,也是学习STL最权威的书籍。作者对书中的50个指导方针都作了详尽的分析,并配以示例。通过这些规则,C++开发者可以最大限度地使用STL。
《Generic programming and the STL(泛型编程与STL)》 本书阐述了泛型程序设计的核心理念:concepts(概念)、modeling(模型)和refinement(改善),并为你展示这些观念如何导出STL的基础概念:iterators(迭代器)、containers(容器)和function objects(函数对象)。按照本书所述,你可以把STL想象成一个由concepts组成的library,你将学习到STL正式结构并理解其强大的优势。
《Exceptional C++ style》 作者为Herb Sutter。本书同样提出了40个C++风格相关的问题,对一些至关重要的C++细节和相互关系提出了新的见解,为当今的关键C++编程技术(如泛型编程、STL、异常安全等)提供了新的策略,帮助开发者在开销与功能之间、优雅与可维护性之间、灵活性与过分灵活之间寻找完美的平衡点。
《C++ template》 这是一本关于C++模板的完整的参考手册和教程,它强调模板的使用实践,包含了现实世界中的例子。每个C++程序员都应该好好读一读这本书。
《Modern C++ design(现代C++设计)》 作者Andrei Alexandrescu为C++程序员打开了一个新的局面。本书提供了一些针对软件设计的前沿方法,如联合设计模式、泛型编程,使程序员可以编写有表现力的、灵活的、高度可重用的代码。
《Thinking in C++(C++编程思想)》 C++ 领域权威著作,介绍了C++实用的编程技术和最佳的实践方法。
以上是用一年时间系统学习C++的建议。
还有一个我最近发现的一个非常赞的视频,是一个国外 C++ 游戏引擎开发工程师录制的一套偏向 talk 类型的教程,比较通俗易懂和深入浅出。

推荐一下:
[中英字幕] C++_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili另外翁凯老师无论是 C、C++、Java 的视频都讲得非常深入浅出,值得学习。
这是网易云课堂地址:
面向对象程序设计-C++ - 网易云课堂最后献上C/C++的一份修炼体系图,希望对大家有帮助:


这里顺便给大家推荐一个github项目,这个项目收录了程序员需要学习的方方面面,包括计算机经典书籍、经典大厂面试题、各种图解tcp/ip、操作系统,欢迎大家访问学习,请不要吝啬您的star:
https://github.com/pinefor1983/祝大家前程似锦,在编码的道路上一马平川。
码字不易,硬核码字更难,希望大家不要吝啬自己的鼓励,给我 :
@findyi
一个点赞,鼓励下我!
pttnow 发表于 2023-10-3 19:26:34|来自:福建 | 显示全部楼层
哈哈,人就是这么矛盾,同期很多一起学编程的同学,都已经搞php,ajax,java,c# 挣的飞起了。可怜我这个娃,还在坚持c++。你说这玩意好用吧。它能干其他高级语言不能干的事情。就是内存操作,和各种延迟调用和延迟配置。你说它不好用吧,总更新有用的语法,于是就得不停地学习。还真就得跟晚辈学习,你说扯淡不? 按理说应该是晚辈跟前辈学习啊。
  就是这么魔幻,因为c++好用,老前辈们就不得不每天在搞应用,就没有时间研究新语法或者某些有用的套路,这些内容,就必须得跟新人去学习,因为他们是有时间进行学习和翻译的,只要他们写的教程是面向中低级程序员的,那么老手就能够看懂这些新语法和新用法。
  所以说, 这个就是一个节奏感,作为新手和老手都应该有自己该做的事情。这样才能够形成人流。否则老人会一直失去技术力,新人则没有办法把各种新技术套用到成熟的解决方案里面。导致落地难的问题。
  另外就是要说一点,每天写代码都很累,每天睡醒也很累,导致看到问题想了办法,刚要打字,就不想打了。只有周末,睡一个懒觉,刚醒来的时候,那个时候,不论什么话题都敢打,多长的内容都敢写。 这也是跟c++打交道的一个弊端。那就是时间根本不够用。 所以说,能够看到这个回答,题主应该给个赞。

快速回帖

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则