编译期类型信息是指数的,运行期类型信息是线性的
来源: gingerbill.org — 2026-09-02
概述
Odin 语言作者 gingerBill 为为何用 RTTI(运行期类型信息)而非 CTTI(编译期类型信息,即模板/泛型特化)辩护。他先澄清「编译期可知」与「编译期可自由枚举」是范畴错误。RTTI 是数据驱动:所有类型信息放进类型表,fmt.println 只是一个遍历表的固定过程,表随类型数线性增长,语义检查零额外开销(没有需要特化的东西),最坏也是 O(N) 且成本可测。CTTI 则四处都是指数代价:每次不同类型组合都生成并单独检查一份代码,实例数从 N 涨到 N×K 乃至 Nᵏ(多项参数的排列组合爆炸),语义检查、代码生成与二进制体积三个地方同时变贵,而这笔编译期+二进制成本恰恰「不可见」,于是被冠以「零成本抽象」之名。他举打印为例:只有 4 种类型、最多 5 个参数的朴素泛型打印可产生上千次实例化,再多加一种类型或一个参数就几何式膨胀。作者认为这是用一个可测的线性内存开销,去换一个看不见的指数编译期开销,很不划算;而且 RTTI 的 typeid 跨 DLL/库边界天然稳定可移植,CTTI 则要求两侧生成逐字一致的实例化。CTTI 也有适用处(热路径无法容忍间接寻址、确需按具体类型优化、且类型组合真的少),但他主张默认 RTTI、只在绝对需要时用 CTTI,并调侃「依赖链接器去重」恰恰等于承认你先生成了大量废代码。
核心要点
区分「编译期可知」与「编译期可自由枚举」:RTTI 是数据驱动——一个过程遍历一张类型表,代码不随类型增长
RTTI 成本:类型表线性增长、查找为固定常量、语义检查零额外(没有要特化的东西),最坏 O(N) 且可测量
CTTI 让每个类型组合都单独生成并检查:实例数从 N 涨到 N×K 甚至 Nᵏ,在语义检查、代码生成、二进制体积三处同时指数化
用可测的线性内存换看不见的指数编译期成本,还美其名曰「零成本抽象」——作者直言讨厌这个词
RTTI 的 typeid 跨动态库边界稳定可移植,CTTI 则要求两侧逐字生成相同的实例化才能互通
CTTI 确有适用场景(无法容忍间接寻址的热路径、确需按类型优化、类型组合真的少),但默认应选 RTTI
金句
It seems that people trade a measurable linear memory cost they can see, for an exponential compile-time cost they cannot see. And all because they cannot see the second one, they have talked themselves into calling it a 'zero-cost abstraction'.(人们拿看得见的线性内存开销,去换看不见的指数编译期开销;正因看不见后者,他们竟说服自己把它称作「零成本抽象」。)
👍 0
点赞
👎 0
沉底
返回 Lobsters 首页