|
作者:lark梳理一下C++的知识体系,温故而知新。文章很长,建议收藏。写在前面✧C++的主战场都2023年了,还在说C++,难道不应该多讲讲golang/rust/python吗?其他公司我不知道,但在至少在腾讯内,如果能把C++代码写好,仍然有不错的饭碗,比如游戏/微信后台等。C++在行业里的主战场,有网友做了一个图,可以看看:谁在蚕食C++的市场?C++的基本盘虽然很稳,但是我们也能感受到一些明显的趋势:--过去几年招聘的时候,优秀的C++程序员越来越不好招,取而代之的是大量的java/golang/python程序员进入市场。--从2020年开始,腾讯PCG开始搞研效工程,在推出trpcgo框架后,很多团队很快就从C++切换到了golang。为什么是golang,从下面这篇文章可以一窥端倪,本文从“performance,simplicity,safety,features,scale,andconcurrency“等几个方面对Golang和Rust做了对比,可以看看:✧C++知识体系为便于快速复习C++语言,本文梳理了C++的知识体系,针对C++的重点和难点做了细致说明,同时给出了可运行的源代码,笔者一直以为通过源代码来学习知识点,是掌握一门语言最快的方式。C++知识体系的搭建基于笔者过往的编程经验,而具体的知识点则参考了知乎上很多优秀文章,所有参考文章都附上了对应链接。关于C++的语言核心:✧新特性:使用新特性有助于简化代码,提高编程效率。例如,一个auto关键字,合理使用可以大大降低大脑和手指的负担,大脑不用记住太多东西,手指也可以少敲很多代码,体会一下这行代码:for(auto&it:vec){...}✧面向对象:继承/多态/运算符重载是对象对象的核心特征,IOStream作为官方库标准库,是使用面向对象的典范✧泛型编程:基于template的编程,可能是C++最强大的地方,这是一种和面向对象完全不同的思维方式,STL是使用泛型编程的典范✧第三方库:编程语言要想发挥巨大作用,必须依赖第三方库,本文重点在语言内核上,对第三方库不做过多介绍关于C++工程化:主要涉及代码构建,单元测试,代码调试,编程环境IDE✧关于学习方法作为程序员,编程语言不仅仅是工具,更是饭碗,须勤学苦练,谈几点笔者的看法:✧每隔两三年学习一门新语言,指望一门语言就能包打天下的时代已经过去了,新生语言在不断蚕食既有语言的地盘,要想不被淘汰,就得紧跟趋势。✧笔者都会什么语言?熟练使用能够端上饭碗的语言有C++/Python/Golang/shell;学过一年以上能够把该语言核心教程里的代码全部跑通的有:PHP/Javascrip/html/css;通读过该语言核心教程并理解其核心思维的有:java/perl/ruby。✧程序员之上是架构师,有扎实编程功底,有良好代码品味的架构师才是货真价实的,否则就是花架子,talkischeap。教学相长,在谈谈笔者对教学方法与学习方法的体会:✧关于教学方法:工作多年的资深开发,一般都要承担传道授业解惑的职责,作为他人导师,通常技术能力和知识结构都没有太大问题,但可以有意识地修炼一下自己的教学方法。headfirst系列的书籍,笔者看过几本,就教学方法而言绝对是上乘之作。✧关于学习方法:在精通一门语言的情况下,如何快速学习一门新语言?在笔者看过的众多编程书籍里面,《PHP&MySQL范例精解——创建/修改/复用》这本书明确提出了一个非常有效的方法:找到工业级代码范例,然后“Create-Modify-Reuse”,这是笔者认为最好的学习方法,代码是最好的老师。1.C++新特性(常用)C++11是C++发展的一个分水岭,从此C++进入了所谓的“现代C++”阶段,往后C++14/17/20持续发展。在腾讯内部,C++的主战场,比如微信后台/游戏后台,笔者咨询过相关部门的资深C++开发同学,除了一些历史遗留代码,新系统的开发一般都用现代C++。就C++具体版本而言,在生产环境中主要还是C++11,例如在微信后台生产环境中gcc的版本是:gccversion7.5.0(GCC),笔者所在部门腾讯视频,云开发机默认是gcc(GCC)4.8.5(RedHat4.8.5-39)(注:截止2023.7)。不同GCC版本支持的C++编译标准:参考:GCC-std编译标准一览表这一节对C++常用的新特性做简明扼要的介绍:参考:https://www.zhihu.com/pub/reader/120162226/chapter/1354802170299080704 1.1.auto&decltypeauto:变量类型推断decltype:表达式类型推断参考:https://zhuanlan.zhihu.com/p/1376627741.2.forrange基于范围的for循环:1.3.function&bind&lambda✓std::function快速创建一个函数对象✓std::bindbind:绑定函数参数✓lambda匿名函数lamdba:创建匿名函数代码示例:使用lambda与不使用lambda的比较:参考:c++11新特性之std::function和lambda表达式:https://zhuanlan.zhihu.com/p/1378844341.4.smartpointerC++11标准在充分借鉴和吸收了boost库中智能指针的设计思想,引入了三种类型的智能指针,即std::unique_ptr、std::shared_ptr和std::weak_ptr1)std::unique_ptrstd::unique_ptrsp=std::make_unique(123);std::unique_ptr禁止复制语义,为了达到这个效果,std::unique_ptr类的拷贝构造函数和赋值运算符(operator=)被标记为delete。2)std::shared_ptrstd::shared_ptrsp=std::make_shared(123);3)std::weak_ptr代码实例:参考:c++是否应避免使用普通指针,而使用智能指针(包括shared,unique,weak)?https://www.zhihu.com/question/319277442/answer/1517987598代码示例:使用auto_ptr时,拷贝或复值导致p1持有的堆对象被转移给sp2:unique_ptr:shared_ptr:1.5.explicit与default与deleteexplicit:只能显示构造,禁止隐式构造(例如,允许Aa(1);但禁止Aa=1)default:声明构造函数为默认构造函数(有了=default,就不用显式定义函数体了)delete:禁止对象的拷贝与赋值delele函数在c++11中很常用,std::unique_ptr就是通过delete修饰来禁止对象的拷贝的。代码示例:代码示例2:1.6.右值引用与移动构造函数本节参考:程序喵大人:左值引用、右值引用、移动语义、完美转发,你知道的不知道的都在这里作用:右值引用与std::move结合,减少对象拷贝附:move函数实现1.7.委托构造与继承构造1.8.random参考:https://www.jianshu.com/p/05863a00af8d代码示例:https://github.com/lxn7022/learn-and-practice/blob/master/c%2B%2B/container/use-vector.cpp1.9.to_string()参考:https://blog.csdn.net/lzuacm/article/details/527049311.10.cstdint参考:https://en.cppreference.com/w/cpp/header/cstdint1.11.新特性系统梳理下面这篇文章对c++各个版本的新特性有系统梳理,用思维导图呈现,很详细:知识点列举,含代码:https://zhuanlan.zhihu.com/p/1395154392.面向对象2.1.对象创建与内存管理new和malloc的区别:delete与delete[]delete只会调用一次析构函数,而delete[]会调用每一个成员的析构函数。在MoreEffectiveC++中有更为详细的解释:“当delete操作符用于数组时,它为每个数组元素调用析构函数,然后调用operatordelete来释放内存。”delete与new配套,delete[]与new[]配套volatile与mutablevolatile:表明所修饰的变量是易变的,例如多线程并发场景,加上voltile用于禁止编译器对变量做优化mutable:作用同volitile,只是mutable只能用于类成员函数。参考:https://zhuanlan.zhihu.com/p/571017611✓代码示例下面这个代码例子,综合展示了前面介绍的各个关键字的使用:代码地址:https://github.com/lxn7022/learn-and-practice/tree/master/c%2B%2B/ringbuffer/v12.2.多继承与内存布局✓简单非多态虚函数+静态数据成员单继承对象的内存布局多重继承+虚函数虚继承内存布局参考:https://zhuanlan.zhihu.com/p/4380062622.3.虚函数与纯虚函数✓虚函数✓纯虚函数参考:https://zhuanlan.zhihu.com/p/37331092✓纯虚函数,代码示例:2.4.运算符重载(C++面向对象精华)✓知识点梳理代码示例代码:https://github.com/lxn7022/learn-and-practice/tree/master/c%2B%2B/overload参考:https://www.cnblogs.com/wanghongyang/p/15014326.html2.5.访问控制✓访问控制✓继承控制注意:默认是private继承,所以通常都要指定public继参考:https://zhuanlan.zhihu.com/p/107709327✓friend函数友元函数可以访问当前类中的所有成员,包括public、protected、private属性的。可以将非成员函数声明为友元函数可以将其他类的成员函数声明为友元函数✓非成员函数的例子:成员函数的例子:提示:可以将友元函数的函数体放在class内,隐式inline✓friend类不仅可以将一个函数声明为一个类的“朋友”,还可以将整个类声明为另一个类的“朋友”,这就是友元类。友元类中的所有成员函数都是另外一个类的友元函数。参考:http://c.biancheng.net/view/2233.html代码:https://github.com/lxn7022/lear3.template模板3.1.函数模板代码示例:参考:https://zhuanlan.zhihu.com/p/381299879https://zhuanlan.zhihu.com/p/1018980433.2.类模板代码示例:参考:https://zhuanlan.zhihu.com/p/381299879https://zhuanlan.zhihu.com/p/1018980433.3.可变参数基本概念:参数包:在函数原型的声明中Args...args同理存在0个或者一个1以上的类型参数,C++中将“typename...Args”这样的语义,称为参数包(parameterpack)。包展开:参数包只有在使用时就必須把它展开变成一个个的参数,概念上称为**包展开(packexpansion)**,将参数包当作普通的参数一样放到被调用函数的参数列表的最后一个位置,并在后面加上...参考:https://zhuanlan.zhihu.com/p/490470765代码示例:通过一个简单示例,理解函数模版中可变参数的作用:代码示例2:3.4.typename与class✧通常两者是等价的:✧有一些场景只能使用typename参考:https://zhuanlan.zhihu.com/p/3357779903.5.STL中的模板泛型编程,C++最强大的地方,也是最复杂的地方基于模版的编程,主要用于程序库的编写,例如STL3.6.元编程关于元编程,主要用于编写程序库,实际工程使用较少:参考:https://zhuanlan.zhihu.com/p/134.STL(泛型编程典范)4.1.容器Container✓整体梳理序列容器:【arrayvector】【queuedequepriority_queuestack】【listforward_list】关联容器:mapset||multimapmultiset关联容器:unordered_mapunordered_set||unordered_multimapunordered_multiset参考下面这个资料,每个容器介绍一遍,根据官方文档整理,简明扼要:https://zhuanlan.zhihu.com/p/542115773[C++STL]各容器简单介绍,有代码示例:https://zhuanlan.zhihu.com/p/130905242根据笔者过去十多年的一线开发经验,尽管每种语言都提供了大量的数据结构,但最常用的似乎就两种,例如○C++里的vector和map,○Python里的list与dict,○Golang里的slice与map,对比以上几种数据结构,这种逻辑上的相似性,似乎揭示了编程语言的某种本质,就像每种编程语言都有循环与控制语句一样。✓vector✧增删改查操作参考:C++中STL---vector详解_c++vector_愚蠢的土拨鼠。的博客-CSDN博客✧vector的迭代器参考:涛哥:STL教程(四):C++STL常用容器之vector✓map参考:【STL】关联容器之map用法总结_舒泱的博客-CSDN博客以下是map的基本操作:✓unordered_map关于unordered_map,有非常多函数,参考下面这篇文章:https://blog.csdn.net/qq_44423388/article/details/126822071https://blog.csdn.net/qq_44423388/article/details/126822071map与unordered_map的区别点:emplace与insert,功能类似,但执行效率更高:为什么emplace的执行效率更高?https://zhuanlan.zhihu.com/p/5999020054.2.算法Algorithm参考下面这篇文章:http://c.biancheng.net/view/7241.htmlc++11新增算法:4.3.迭代器Iterator4.4.STL使用介绍参考下面这篇文章:http://c.biancheng.net/view/7241.html5.IO流(面向对象典范)5.1.iostream技术原理:代码示例:代码:https://github.com/lxn7022/learn-and-practice/blob/master/c%2B%2B/stream/use-iostream.cpp5.2.fstream代码示例:https://github.com/lxn7022/learn-and-practice/blob/master/c%2B%2B/stream/use-fstream.cpp5.3.stringstream知识点梳理:代码示例:https://github.com/lxn7022/learn-and-practice/blob/master/c%2B%2B/stream/use-sstream.cpp5.4.strstream知识点梳理参考:https://zhuanlan.zhihu.com/p/123177742代码示例:6.代码构建6.1.选择什么工具参考:靖哥哥吃糖:C++编译之makecmakebazel模板几种构建工具的对比,可以参考:如何评价Google开源的Bazel?6.2.make与Makefile在腾讯公司内部,系统架构从整体上来说,基本都是微服务模式,即很多小模块以rpc的方式构成一个大的分布式系统,每个模块的规模都不是很大,因此C++开发一般都用make来编译和构建。下面是笔者使用的一个Makefile模版:6.3.cmake与CMakeLists.txtCMakeLists.txt主要通过函数的方式来组织编译规则,下面是一个示例文件:6.4.bazel与BUILD从2018开始,腾讯的研发体系发生了巨大变革,从以往的DO分离逐步变成了CI/CD,传统的运维消失了。反映在C++开发上,版本管理从svn切换到了git,构建工具逐步从make逐步切换到了bazel。另一方面,过去C++坚固的阵地发生了松动,golang以其简单和高性能在逐步蚕食C++的地盘。下面是bazel配置文件的写法,相比make和cmake更可读:6.5.腾讯的工程实践在腾讯内部,代码管理经历了不同阶段,不同部门也有不同的代码管理规范,下面这篇文章介绍的内容很有代表性:文章地址:腾讯技术工程:微信小仓实践录|后端代码仓库发展史7.单元测试写好单元测试,让代码时刻处于可运行状态,代码只有跑起来才叫代码,跑不起来的那叫伪代码。7.1.单测概念7.2.单测框架GoogleTest官方文档:入门:https://github.com/google/googletest/blob/master/docs/primer.md进阶:https://github.com/google/googletest/blob/master/googletest/docs/advanced.mdGoogleMock官方文档:入门:https://github.com/google/googletest/blob/master/googlemock/docs/for_dummies.md进阶:https://github.com/google/googletest/blob/master/googlemock/docs/cheat_sheet.mdhttps://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md7.3.单测实战详细内容参考,【金山文档】CPP单元测试实战:https://kdocs.cn/l/ctiKaoV1hX3j8.代码调试8.1.gdb调试C/C++代码,最著名的工具就是gdb,但坦白说笔者用的并不多,在过往十多年的编程生涯里,用gdb的次数不会超过十次:)常用的gdb命令:参考:大佬们都是怎么用gdb的?或者用吗?8.2.通用方法不用gdb并不代表不调试代码,笔者总结了调试代码的三板斧:print+log+unittest大部分时候就用print,用不了print就打log,近几年体会到了单测的威力,就开始写单测调试代码的三板斧,不光适用于C/C++,其他编程语言例如python/golang/shell等,都统一适用这三板斧,平淡无奇人人都会,没有gdb的逼格,但用好了基本可以解决99%的问题,不low!9.工具链IDE9.1.Vscode上配置C++11环境 ✧配置过程✧vscode配置选项配置文件:"-std=c++11","-stdlib=libstdc++","-Wc++11-extensions",9.2.Git与Github代码管理,不管是在公司内部还是在社区,现在一般都用Git。常用命令请参考:✧靠代码吃饭的人,建议开通自己的github账号✧没事的时候就码几行代码,时刻保持良好的技术状态:9.3.Vim写代码这个事情,一练脑子,二练手指。学会vim,形成肌肉记忆,自然能体会到其妙处在linux环境下,经常用vim对文本文件做一些简单的增删改查编辑操作,老司机一般都会用,建议新手做简单学习:
|
|