本系列文章记载学习一门在线课程 罗剑锋的C++实战笔记 过程中的心得体会,只会记录新增加的知识点,那些心中已熟透的知识点,不会重复记录。
c++
的主战场在 Linux
上,现在开发 Windows
程序,更多的是用 C#
等语言。
后续以问答的形式,来梳理汇总新掌握的注意事项和经验教训。
三句名言镇楼
-
任何人都能写出机器能看懂的代码,只有优秀的程序员才能写出人看懂的代码
-
两种写程序的方式:把代码写的非常复杂,以至于"看不出明显错误"。把代码写的非常简单,以至于"明显看不出错误"。
-
把正确的代码改快速,要比把快速的代码改正确,容易得太多。
如何查看gcc对c++标准的支持情况?
- 通过
g++ -v
得到g++
版本号。例如:本机版本号为gcc version 7.5.0
- 下图为不同
gcc
版本对C++
标准的支持情况。
更为具体的,可以参考 C++ Standars Supprot in GCC 网站,查看各个标准在各个编译器的支持情况。
C++有哪些编程范式?
编程范式是指导编写代码的思路、规则、习惯和常用方法的统称,是一种方法论
。
现代C++
(C++11
以后)支持以下五种编程范式:
- 面向过程:
if
、else
、switch
,核心是功能分解为具体步骤,依次执行这些步骤。 - 面向对象:
class
、public
、virtual
, 核心是功能抽象为各种类,将数据以及职责封装进对应类,通过类对象之间的协作实现功能。以抽象和封装为基础,继续抽象对象之间的关系和通信,最后构成由许多相关联的对象系统。 - 泛型:
template
、vector
,核心是将类型当做参数,利用模板来复用代码。 - 模板元编程:
template
、struct
、enable_if
,核心是编译期间类型运算,代码由编译器执行。 - 函数式:
lambda
,核心是一切皆函数,皆可调用。
日常工程开发中,使用 面向对象
+泛型
,少量函数式
,不用模板元
。
代码规范
留白: 恰当地运用空格和空行,空格用来分隔变量和操作符,空行用来分隔逻辑代码块,使得整体错落有致,舒缓得当,更易理解。
注释:正确、清晰、简洁。从使用者和阅读者的角度出发,来看待注释。
类设计:少用继承,多用组合。控制继承的层次,用 UML
类图来主观检查。
接口设计:简单直接,只负责单一功能。
预处理过程中需要注意的地方
- 宏是没有作用域的,默认全局生效。为避免宏定义冲突,有两种解决方法:
- 使用完后使用
#undef
来取消宏定义
#define CUBE(a) (a) * (a) * (a) cout << CUBE(a); #undef CUBE
- 在使用前,先进行检查。如果之前有定义,则取消定义。
#ifdef AUTH_PWD # undef AUTH_PWD #endif #define AUTH_PWD "XXX"
- 使用完后使用
编译阶段能做的事
属性标签
C++11
使用两对方挂号的形式 [[ ... ]]
,方挂号中间是属性标签。deprecated
的编译期标签,标记已废弃的变量、函数。
[[deprecated("deadline:xxxx")]]
int old_fun()
{}
常用的属性标签:
unused
: 用于变量、类型和函数等,表示暂时不用,但最好保留constructor
: 指示函数会在main
函数之前执行destructor
: 指示函数会在main
函数之后执行always_inline
: 要求编译器强制内联hot
: 标记为热点函数,可更积极优化noreturn
: 指示函数不会有返回值
静态断言
常用的assert
函数只能在运行期生效,对应的,在编译期生效的断言为 static_assert
,将检测时机提前到编译期。
标准库的 type_traits
,它提供了各种编译期函数,可进行更为细致的判断。
特殊功能标示符
final
标识符用于类定义,可显式禁用继承。
= default
标识类的基本函数由编译器实现。
自动类型推导
auto
总是推导出值类型,可附加const
、volatile
、&
类型修饰符,得到新的类型。
auto x= 10L; // 推导为 long
auto& x1 = 1; //推导为 long&
auto* x2 = &x; // 推导为 long*
const auto& x3 = x; // 推导为 const long&
decltype
的形式类似于函数,后面的圆括号用于计算类型的表达式。它不仅能推导出值类型,还能够推导出引用类型。
自我总结: auto
是从值来推导数据类型,decltype
是从变量自身来推导数据类型。