The efficiency of different C++ constructs3

简介: The efficiency of different C++ constructs3

模板


模板与宏的相似之处在于,模板参数在编译之前被它们的值所替换

模板是高效的,因为模板参数总是在编译时被解析。模板使源代码更加复杂,而不是编译后的代码。一般来说,使用模板在 执行速度方面没有任何成本




使用模板实现编译时多态


模板类可用于实现编译时多态性,这比使用虚拟成员函数获得的运行时多态性更加高效

模板代码可读性不佳。如果编译器能够自动执行去虚拟化(去掉动态绑定时对虚函数表的查询), 那么依赖编译器优化肯定比使用这种复杂的模板方法更加方便。




线程


线程上下文切换非常耗时,可通过设置更长的时间片来减少上下文切换的次数。

为不同任务的不同线程分配不同的优先级是非常有用的


为了充分利用多核,我们将工作划分成多个线程,每个线程在单独的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。




预处理命令


就程序性能而言,预处理指令(以#开头的所有指令)的性能成本很少,因为它们在程序编译之前就已经解析了




命名空间


使用名称空间,对执行速度没有影响

相关文章
|
存储 缓存 并行计算
The efficiency of different C++ constructs5
The efficiency of different C++ constructs5
115 0
|
存储 缓存 编译器
The efficiency of different C++ constructs4
The efficiency of different C++ constructs4
98 0
|
存储 缓存 Unix
The efficiency of different C++ constructs2
The efficiency of different C++ constructs2
113 0
|
缓存 编译器 C++
The efficiency of different C++ constructs
The efficiency of different C++ constructs
124 0
|
29天前
|
C++ 容器
C++中自定义结构体或类作为关联容器的键
C++中自定义结构体或类作为关联容器的键
30 0
|
29天前
|
存储 算法 搜索推荐
【C++】类的默认成员函数
【C++】类的默认成员函数
|
8天前
|
存储 编译器 C++
C ++初阶:类和对象(中)
C ++初阶:类和对象(中)
|
8天前
|
C++
C++(十六)类之间转化
在C++中,类之间的转换可以通过转换构造函数和操作符函数实现。转换构造函数是一种单参数构造函数,用于将其他类型转换为本类类型。为了防止不必要的隐式转换,可以使用`explicit`关键字来禁止这种自动转换。此外,还可以通过定义`operator`函数来进行类型转换,该函数无参数且无返回值。下面展示了如何使用这两种方式实现自定义类型的相互转换,并通过示例代码说明了`explicit`关键字的作用。
|
8天前
|
存储 设计模式 编译器
C++(十三) 类的扩展
本文详细介绍了C++中类的各种扩展特性,包括类成员存储、`sizeof`操作符的应用、类成员函数的存储方式及其背后的`this`指针机制。此外,还探讨了`const`修饰符在成员变量和函数中的作用,以及如何通过`static`关键字实现类中的资源共享。文章还介绍了单例模式的设计思路,并讨论了指向类成员(数据成员和函数成员)的指针的使用方法。最后,还讲解了指向静态成员的指针的相关概念和应用示例。通过这些内容,帮助读者更好地理解和掌握C++面向对象编程的核心概念和技术细节。
|
29天前
|
存储 安全 编译器
【C++】类和对象(下)
【C++】类和对象(下)
【C++】类和对象(下)