我的理解是,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
\box
IE将框视为任何其他“变量”,代价是占用内存。当然,对于现代 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 的内容,则需要数据结构的第二个实例的原因。