面向对象带来的性能损耗
关于对象的构成可以参考之前的一篇博客,C++对象
- 缓存开销
数据被组织在对象内,然后对象又有一些额外的内存开销,比如虚表等。
- 方法开销
面向对象有很多的小函数,函数调用耗时,小的区块也限制了编译器优化的空间,虚函数机制多次跳转也有损耗。
- 构造开销
构造函数开销大,有可能要处理虚继承虚函数的情况。
JAVA中:
- 在堆上分配空间,调用类的构造函数,初始化类的字段
- 对象状态被垃圾收集器跟踪,可能发生垃圾回收
- 在使用调试器创建对象时,你可以在一定程度上看到这一点。
**C++**中:
- 拷贝构造经常发生(传参赋值返回),JAVA中都是引用就不会潜在发生。
- 构造与解构在继承体系中都是链状的,call的开销也很大
- 异常
这个可以参考之前写的异常处理,讲到try catch的实现,里面其实就是很多的跳转,还是非局部的,也就是很像function call。消耗当然大了。
优化
Method In-lining
编译器很难自己去in-lining,c++的in-line关键字也只是鼓励编译器尝试in-line函数。但还是多用inline关键字。
一般对于带循环的小函数编译器不会inline它,所以建议用重复的几行来替代小循环。
私有,final的方法很可能被inline但是虚函数从不会被inline因为需要在运行时间接调用
nested template:
template <template <typename, typename...> class V, typename... Args>
void print_container(V<Args...> &con)
这需要C++11支持,template <typename, typename…> class V是第一个模板参数,他是一个有typename, typename…为模板参数的类,它的名字叫V,typename… Args指后续的模板参数,数量任意多,Args就是V里的模板参数,需要在这里指示出来。这是C++11的写法,可以让编译器自动推导传入类型模板参数的数量和类型。
举个例子,
vector<vector<vector<int>>>的参数传进去,推导出来就是这个:
void print_container<std::vector, std::vector<std::vector<int>>, std::allocator<std::vector<std::vector<int>>>>(std::vector<std::vector<std::vector<int>>> &con)
Encapsulation
意思就是把性能差的部分拿出来单独放到一个区域中或类中,在辅助上硬件比如FPGA,GPGPU,可以达到不错的加速效果。