为什么 \boxN 会清除盒子?

为什么 \boxN 会清除盒子?

我的理解是,wlog\box0会放入 box 0 的内容,并且会清除 box 0 的内容,而 wlog\copy0会放入 box 0 的内容,并且完全不改变 box 0 的内容。

每当我这样做时\sbox0{All New Content},我都会覆盖存储在框 0 中的所有内容,并将其替换为“所有新内容”。

为什么在使用盒子时删除盒子的内容如此重要,以至于将其作为默认行为?关于编译,有人可能会建议保持盒子不变会更快,因此我们应该延迟删除盒子的内容,直到有必要时,即当我们想将新内容放入盒子时。

答案1

在编写 TeX 时,节省内存非常重要。通常,当一个框被使用后,原来的框中的内容就不再需要了(IE它会被移动到其他盒子中),因此可以通过\box清除盒子的行为方便地回收内存。如果不是这种情况,\copy则可用。值得注意的是,盒子不是固定项目,与计数寄存器不同,因此需要避免累积。

值得注意的是,LaTeX 的行为不是\usebox建立在\copy\boxIE将框视为任何其他“变量”,代价是占用内存。当然,对于现代 TeX 系统来说,\box由于内存原因,确实没有必要经常使用它(尽管如果知道不需要内容,也没有特别的理由不回收它)。

答案2

约瑟夫赖特 (Joseph Wright) 的回答很中肯:在定义处理盒子寄存器的原语时,节省内存是 Knuth 最关心的问题。

但也存在一些微妙之处。

盒子寄存器可以为空,也可以包含水平盒子(来自\hbox)或垂直盒子(来自\vbox\vtop)。

如果你这样做\box0(零可以是任何其他有效的寄存器编号)并且寄存器无效,则什么也不会发生。否则盒子交付的是箱子,而不是箱子里的内容。箱子里的内容可以用\unhbox或交付\unvbox,具体取决于存放在收银机中的箱子类型。1

事实上,一个盒子可能会占用大量内存(当然,与 TeX 开发年代的计算机内存相比,这个内存是巨大的),因此在交付内置盒子后回收这些内存\setbox是最重要的。

盒子还有另一个特殊之处。我们知道,打开一个组并设置一个变量会激活在​​组结束时恢复变量值的机制。这也适用于盒子,但为了节省内存,如果您在组外构建了一个盒子并将其传递到内部,则盒子寄存器将在上层被销毁!

\setbox0=\hbox{ABC}
\begingroup\setbox0=\box0\endgroup
\box0

不会产生任何输出。确切地说,最新的化身\box0将被销毁。所以如果你这样做

\setbox0=\hbox{ABC}
\begingroup\setbox0=\hbox{DEF}\box0\endgroup
\box0

最后一条命令将输出与 相同的结果\hbox{ABC}。换句话说,TeX 不会在结束组时启动恢复盒子寄存器的机制,除非必须这样做,即\setbox在组内使用。

除了以下之外,还有六个原语可以处理盒子寄存器\setbox

\box      \copy
\unhbox   \unhcopy
\unvbox   \unvcopy

右列中的不会破坏寄存器的内容。

LaTeX\sbox构建一个水平框,因为它定义为

% latex.ltx, line 4796:
\long\def\sbox#1#2{\setbox#1\hbox{%
  \color@setgroup#2\color@endgroup}}

同样地,\savebox存储一个水平框。请注意防止颜色滴落的保护(如果color加载,它们将被激活)。宏\usebox总是这样做\copy

% latex.ltx, line 4819:
\def\usebox#1{\leavevmode\copy #1\relax}

最后说明:如果\setbox(或基于其构建的宏)在组内完成,则当组结束时,寄存器将恢复到之前的状态(除非如前所述,某些\box命令具有


1如果盒子寄存器为空,TeX 可能会切换模式(如果有必要),具体取决于是否使用\unhbox或。工作原理如下:它会执行,前提是盒子寄存器永久为空。\unvbox\leavevmode\unhbox\v@idbox\v@idbox

答案3

TeX 中的框(粗略地说)被实现为指向包含在该框中的排版材料的垂直/水平列表的指针,并且该数据结构可能很大并且驻留在主 TeX 内存中。当您说\box0在外部材料的某个位置时,只有指针放在这里,并且 box0 的指针被重新设置为 NULL。保存在主内存中的先前 \box0 的内容保持不变。从机器的角度来看,这种“仅指针”操作非常简单且成本低廉。另一方面,\copy0在主内存中创建相同数据结构的第二个副本,因为第一个实例指向 \copy0 的位置,而第二个实例保留 box0 的内容。

之后,盒子会从内存中删除\shipout。想象一下,\copy0在 ed 盒子的某个地方使用\shipout。此内容被删除。这就是为什么如果您需要保留 box0 的内容,则需要数据结构的第二个实例的原因。

相关内容