C++拾趣——使用多态减少泛型带来的代码膨胀

栏目: C++ · 发布时间: 6年前

内容简介:泛型编程是C++语言中一种非常重要的技术,它可以让我们大大减少相似代码编写量。有时候,我和同事提及该技术时,称它是“一种让编译器帮我们写代码的技术”。C++是一门静态语言,它最终的编译成果是可以直接运行于冯诺依曼体系的计算机上,而不像其他动态语言,需要运行于虚拟机等容器中。由于对运行效率得追求,C++也是一门类型精确的语言,即object是什么类型,在编译时往往就要确定好,这种方式可以称为数据的静态绑定。上例中,我们只写了一个call_function模板函数,但是最终编译器会将其翻译成为两个独立的函数,

泛型编程是C++语言中一种非常重要的技术,它可以让我们大大减少相似代码编写量。有时候,我和同事提及该技术时,称它是“一种让编译器帮我们写代码的技术”。

C++是一门静态语言,它最终的编译成果是可以直接运行于冯诺依曼体系的计算机上,而不像其他动态语言,需要运行于虚拟机等容器中。由于对运行效率得追求,C++也是一门类型精确的语言,即object是什么类型,在编译时往往就要确定好,这种方式可以称为数据的静态绑定。

template<class T>
void call_function(T& f) {
	f();
};

class PrintA {
public:
	virtual void operator ()() {
		std::cout << "Print A" << std::endl;
	}
};

class PrintB : public PrintA {
public:
	virtual void operator ()() {
		std::cout << "Print B" << std::endl;
	}
};

int main() {
	PrintA a;
	PrintB b;
	call_function(a);
	call_function(b);
	return 0;
}

上例中,我们只写了一个call_function模板函数,但是最终编译器会将其翻译成为两个独立的函数,分别是call_function<PrintA>()和call_function<PrintB>()。这也是之前所述“一种让编译器帮我们写代码的技术”的表现。

我们逆向上述代码来验证下

C++拾趣——使用多态减少泛型带来的代码膨胀

上图我们看到call_function<PrintA>()和call_function<PrintB>()方法的地址是不同的。这就意味着,这两个方法拥有各自的代码逻辑。再上升一个层次去看,使用call_function的模板方法的类有多少种,就会产生多少个相应的特化方法。于是我们的确只写了一个模板方法,但是编译器最终帮我们生成了多个,于是便发生了“代码膨胀”。

编译器将类型特化,即精确指定了类型,这就使得C++程序在运行时直接跳转到相应函数地址就行,而不需要做类型判别后去路由。这也是C++高效的一个重要原因。

除了静态绑定,C++还有半动态绑定。这也是C++实现多态的技术基础。我们可以使用该技术,部分的解决泛型技术带来的“代码膨胀”的问题。

以上例为例,我们只要增加如下方法就行

void call(PrintA& f) {
	f();
}

然后调用call(a)和call(b)

C++拾趣——使用多态减少泛型带来的代码膨胀

可以看到,两次调用的call方法指向了同一个地址。于是不管call方法操作的类型有多少个,它都没有导致代码的膨胀。

需要指出的是,泛型和多态在上例中,体现了“空间”和“时间”的选择问题。当我们在做优化代码时,往往最终会走到“时间换空间”或者“空间换时间”的选择中。

上例泛型技术,生成了多份函数。在调用时,方法对应的函数地址是确定的,于是这是种调用是高效的。这是“空间换时间”的案例。

上例多态技术,只生成了一份代码。在调用时,call方法需要找到object的虚表,然后计算出虚函数的地址,最后才能调用相应的虚函数。这个过程没有直接call一个地址快。这是“时间换空间”的案例。

目前CPU的发展已经进入瓶颈,磁盘的空间却越来越便宜。很多人可能觉得“空间换时间”是个更好的选择,其实不可以一概而论。因为如果程序的最终编译产物小,其在CPU指令缓存中发生了cache miss也可能变小,最终效率可能还是可观的。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

垃圾回收的算法与实现

垃圾回收的算法与实现

中村成洋、相川光 / 丁灵 / 人民邮电出版社 / 2016-7-1 / 99.00元

★ Ruby之父Matz作推荐语:上古传承的魔法,彻底揭开垃圾回收的秘密! ★ 日本天才程序员兼Lisp黑客竹内郁雄审校 本书前半介绍基本GC算法,包括标记-清除GC、引用计数、复制算法的GC、串行GC的算法、并发GC的算法等。后半介绍V8、Rubinius、Dalvik、CPython等几种具体GC的实现。本书适合各领域程序员阅读。一起来看看 《垃圾回收的算法与实现》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

在线进制转换器
在线进制转换器

各进制数互转换器

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具