什么是“ Thunk”?

我见过它在编程中使用(特别是在 C + + 领域) ,但不知道它是什么。也许这是一种设计模式,但我可能错了。有人能给出一个很好的例子吗?

40827 次浏览

单词 thunk 在计算机科学中至少有三种相关的含义。“ thunk”可以是:

  • 执行延迟的一段代码 计算(类似于闭包)
  • 某种虚拟函数的特征 表实现(类似于 包装函式)
  • 从一个机器数据到另一个机器数据的映射 系统特定的形式到另一个, 通常是为了兼容性

我通常在第三种语境中看到它的使用。

Http://en.wikipedia.org/wiki/thunk

一些面向对象语言(如 C + +)的编译器会生成名为“ thunk”的函数,以便在存在多个或多个虚继承的情况下优化虚函数调用。

摘自: http://en.wikipedia.org/wiki/Thunk#Thunks_in_object-oriented_programming

这个问题已经被问过了,请参阅:

什么是 a-thunk,用于 Scheme 或一般情况下?

在我看来,它类似于 lambda 语句,你可能不想返回值,除非你需要计算它; 或者它也可以比作一个属性 getter,通过设计执行一些代码来返回一个值,同时具有接口形式,看起来更像一个变量,但也具有多态行为,可以通过继承或交换的函数指针,将计算和返回一个值在运行时基于编译时或环境特征。

我打算查一下,但我以为 思考是32位处理器用来运行遗留的16位代码的过程。

我过去常常用它作为一个类比,来说明你必须限制自己说话的速度,以及在与哑巴交谈时使用哪些词语。

是的,它在维基百科的链接(关于32位的部分,不是我的 书呆子)。

Https://en.wikipedia.org/wiki/thunk

许多关于互操作性主干的文献都与各种 Wintel 平台有关,包括 MS-DOS、 OS/2、[8] Windows [9][10]和。NET,以及从16位内存寻址到32位内存寻址的转换.随着客户从一个平台迁移到另一个平台,thunk 对于支持为旧平台编写的遗留软件至关重要。

(强调由我添加)

使用方法有很大的差异。几乎普遍地,thunk 是一个(至少在概念上)非常小和简单的函数。它通常是某种类型的适配器,为您提供与某些事物或其他事物(某些数据、另一个函数等)的正确接口,但至少看起来没有什么其他功能。

它几乎就像一种语法糖,只不过(至少和通常使用的一样)语法糖应该让事物看起来像人类读者希望看到的样子,而 Thunk 是让事物看起来像编译器希望看到的样子。

thunk通常引用一小段代码,这段代码被作为函数调用,做一些小事情,然后 JUMP到另一个位置(通常是一个函数) ,而不是返回给它的调用者。假设 JUMP 目标是一个普通函数,当它返回时,它将返回到 thunk 的调用者。

Thunk 可以用来高效地实现许多有用的东西

  • 协议转换——当从使用一种调用约定的代码调用使用不同调用约定的代码时,可以使用 thunk来适当地转换参数。这只有在返回约定兼容的情况下才有效,但情况往往如此

  • 虚函数处理——在 C + + 中调用多重继承基类的虚函数时,需要修复 this指针,使其指向正确的位置。thunk可以做到这一点。

  • 动态闭包——当您构建动态闭包时,闭包函数需要能够访问创建它的上下文。可以构建一个小的 thunk(通常在堆栈上) ,它在一些寄存器中设置上下文信息,然后跳转到实现闭包函数的一段静态代码。这里的 thunk 有效地为函数提供了一个或多个隐藏的额外参数,而这些参数不是由调用站点提供的。

我苦恼地发现,没有一个通用的“计算机科学”的定义,符合这个术语的实际用法,因为历史上已知的我。我记得第一次在现实生活中遇到它是在 OS/2和16-32位转换的时候。在今天的应用中,“思考”似乎就像是一种讽刺。

我的粗略理解是,thunk 是一个存根例程,它只是不做任何事情,或者像上面提到的历史案例那样,在系统之间以某种方式跨越一些基本边界。

因此,这种感觉就像是从一个环境掉到另一个环境的联觉,发出“ Thunk”的声音(比喻/比喻)。

术语 thunk 最初指的是 Algol60编译器中按名称传递的 皇家雷达设施实现所使用的机制。一般来说,它指的是在引用一个明显静态的对象时诱发动态行为的任何方法。这个术语是由 Brian Wichmann 发明的,当被要求解释按名称传递时,他说: “你出去从内存中加载值,然后突然想到,你正在计算一个表达式。”

Thunk 已经被放到硬件中(参见 KDF9,Burroughs 大型机)。有几种方法可以在软件中实现它们,都是机器、语言和编译器特有的。

这个术语已经被广义化,超出了按名称传递的范畴,包括了表面上或名义上静态的数据引用导致动态行为的任何情况。相关术语包括“蹦床”和“未来”。

根据 凯尔 · 辛普森的定义,谢谢是从异步代码中抽象出 时间组件的一种方法。

我所知道的“ thunk”的最早使用是在50年代末期,当时是在函数调用中参照 Algol60的按名称传递参数求值。Algol 最初是一种规约语言语言,而不是一种编程语言,关于如何在计算机上实现名字传递(pass-by-name)存在一些问题。

解决方案是通过本质上是 lambda 的入口点。当被调用方计算该参数时,控制失败了-Thunk!- 进入调用方的上下文,在这里对 lambda 进行求值,其结果成为被调用方中参数的值。

在带标记的硬件中,比如 Burroughs 机器,计算是隐式的: 参数可以像普通的通过值传递(pass-by-value)一样作为数据值传递,也可以通过 thunk 进行通过名称传递(pass-by-name) ,在参数元数据中使用不同的标记。加载操作硬件检查标记并返回简单值或自动调用 lambda thunk。

新黑客词典的早期版本声称 谢谢是一个不需要参数的函数,它是一个特别棘手问题的简单的深夜解决方案,“ thunk”是“ think”的过去式,因为他们早就应该想到它了。

在 OCaml 中,它是一个以单位“()”作为参数的函数(不接受参数,通常用于副作用)