模板
模板与宏的相似之处在于,模板参数在编译之前被它们的值所替换
模板是高效的,因为模板参数总是在编译时被解析。模板使源代码更加复杂,而不是编译后的代码。一般来说,使用模板在 执行速度方面没有任何成本
使用模板实现编译时多态
模板类可用于实现编译时多态性,这比使用虚拟成员函数获得的运行时多态性更加高效
模板代码可读性不佳。如果编译器能够自动执行去虚拟化(去掉动态绑定时对虚函数表的查询), 那么依赖编译器优化肯定比使用这种复杂的模板方法更加方便。
线程
线程上下文切换非常耗时,可通过设置更长的时间片来减少上下文切换的次数。
为不同任务的不同线程分配不同的优先级是非常有用的
为了充分利用多核,我们将工作划分成多个线程,每个线程在单独的cpu core上执行。但是多线程有四个成本:
- 启动和停止线程的成本。如果任务执行时间很短,不要为其单独分配线程
- 线程切换成本。
- 线程间同步和通信成本。
- 不同线程需要单独的存储空间,线程有各自的堆栈,如果线程共享相同的缓存,可能会导致缓存竞争。
多线程程序必须使用线程安全函数,线程安全函数永远不应该使用静态变量(除非只读)
异常和错误处理
c++中通过try catch捕获异常。异常处理旨在检测很少发生的错误,并以一种优雅的方式从错误条件中恢复
虽然程序运行时没有错误,但是异常处理仍需要额外的时间,花销多少取决于编译器实现。
如果你的应用程序不需要异常处理,那么应该禁用它,以便使代码更小、更高效。你可以通过关闭编译器中的异常处理选项来禁 用整个程序的异常处理。你也可以通过向函数原型中添加 throw() 声明来禁用单个函数的异常处理:
异常和向量代码
向量指令对于并行执行多个计算是有用的。
如果代码可以从向量指令中获益,那么最好禁用异常捕获,转而依赖 NAN 和 INF 的传递。
避免异常处理的成本
当不需要尝试从错误中恢复时,不需要异常处理。
建议使用系统的、经过深思熟虑的方法来处理错误。你必须区分可恢复错误和不可恢复错误;确保分配的资源在发生错误时 得到清理;并向用户发送适当的错误消息。
编写异常安全代码
为了保证异常安全,需要在发生异常时清理资源
- 使用new和malloc分配的内存
- 句柄
- 互斥量
- 数据库连接
- 网络连接
- 待删除临时文件
- 待保护的用户工作
- 其他已分配的资源
C++ 处理清理工作的方法是创建一个析构函数。C++ 异常处理系统确保调用本地对象的所有析构函数。 如果包装器类有析构函数来处理分配资源的所有清理工作,则程序是异常安全的。如果析构函数引发另一个异常,则系统可能会出现问题。
如果你使用自己的错误处理系统而不是使用异常处理,那么你无法确保调用了所有析构函数并清理了资源。如果错误处理程 序调用 exit()、abort()、_endthread() 等,则不能保证所有析构函数被调用
NAN和INF的传递
浮点溢出和除以 0 得到无穷大。如果你把无穷大和某数相加或相乘,结果就是无穷大。 如果用一个正常的数字除以INF,会得到0 。特殊情况INF‐INF和INF/INF得到NAN (not‐a‐number)。当你用 0 除以 0 以及函数的输入超出范围时,比如sqrt(‐1)和log(‐1),也会出现 特殊的代码NAN。
INF 和 NAN 的传播也不需要额外的成本
当参数为 INF 或 NAN 时,函数 finite() 将返回 false,如果它是一个普通的浮点数,则返回 true。
预处理命令
就程序性能而言,预处理指令(以#开头的所有指令)的性能成本很少,因为它们在程序编译之前就已经解析了
命名空间
使用名称空间,对执行速度没有影响