由于\newsavebox{\name}
将盒子注册号分配给,因此最多可能有 256 个盒子可用。完成之后\name
有没有办法释放?\savebox
答案1
正常模型是分配一次框(在文档开始之前)并在定义的宏中多次使用它,因此限制通常不是问题,但是所有现代发行版都使用基于 etex 的 LaTeX 格式,在这种情况下有 32768 个寄存器可用(尽管您需要\usepackage{etex}
向 latex 声明这一点并使用了解寄存器的分配方案。
答案2
正如其他人提到的,LaTeX 没有提供释放未使用寄存器的方法。这比您的示例代码所建议的要困难一些,因为您可以在需要填充的已分配寄存器列表中添加“空洞”;跟踪它们会很麻烦或很慢。
如果你发现自己需要使用很多很多你想释放的寄存器,那么etex.sty
在宏下有“本地”寄存器分配
\loccount
\locdimen
\locskip
\locmuskip
\locbox
\loctoks
\locmarks
下面显示了一个示例;您可以看到同一个框以不同的名称被分配了两次。
\documentclass[a4paper]{article}
\usepackage{etex}
\begin{document}
\begingroup
\locbox\textbox
\savebox\textbox{this is box \the\textbox: some text}
\fbox{\usebox\textbox}
\endgroup
\begingroup
\locbox\textboxB
\savebox\textboxB{this is box \the\textboxB: some more text}
\fbox{\usebox\textboxB}
\endgroup
\end{document}
为了有效,您需要分组,但如果您对保存框有如此巨大的需求,那么您可能无论如何都会在某种程度上进行分组。
答案3
如果您使用临时框寄存器(如 \box0),则必须确保不会调用使用相同框的宏,并且必须希望更新版本或包替换永远不会使用它。但是,如果您使用 \newsavebox,那么对于使用 \newsavebox 的其他人而言,它是安全的(直到您使用 \freebox 释放它)。
\documentclass{article}
\makeatletter
\newcounter{free@boxes}% push stack counter
\newcounter{free@count}% loop counter
\global\let\old@savebox=\newsavebox% save original version
\global\chardef\free@min 255
\global\chardef\free@max 0
\newcommand*{\freebox}[1]% #1 = old savebox name
{\newif\ifgood\goodtrue%
\ifnum#1<\free@min \goodfalse\fi%
\ifnum#1>\free@max \goodfalse\fi%
\ifnum\value{free@boxes}=0\relax%
\else\setcounter{free@count}{\value{free@boxes}}%
\loop% check for duplicates
\ifnum#1=\csname free@box\arabic{free@count}\endcsname
\goodfalse%
\setcounter{free@count}{0}%
\else\addtocounter{free@count}{-1}\fi%
\ifnum\value{free@count}>0 \repeat%
\fi %
\ifgood\stepcounter{free@boxes}%
\global\expandafter\let\csname free@box\arabic{free@boxes}\endcsname#1%
\fi%
\global\chardef#1 0}
\renewcommand*{\newsavebox}[1]{% #1 = new savebox name
\ifnum\value{free@boxes}>0%
\global\edef#1{\csname free@box\arabic{free@boxes}\endcsname}%
\addtocounter{free@boxes}{-1}%
\else\old@savebox{#1}%
\ifnum#1<\free@min \global\let\free@min=#1 \fi%
\ifnum#1>\free@max \global\let\free@max=#1 \fi%
\fi}
\makeatother
\begin{document}
\newsavebox{\test}
\savebox{\test}{This is a test}
\usebox{\test}
\newsavebox{\testb}
\savebox{\testb}{This is the second test}
\usebox{\testb}
\freebox{\test}% release box registers for reuse
\freebox{\testb}
\newsavebox{\reuseb}% push stack returns second box first
\usebox{\reuseb}
\newsavebox{\reuse}
\usebox{\reuse}
The following have been reset to zero:\newline
\verb$\test$ \the\test\newline
\verb$\testb$ \the\testb
\makeatletter
The following should all equal the first box register value:\newline
\verb$\reuse$ \the\reuse\newline
\verb$\free@box1$ \the\csname free@box1\endcsname
The following should all equal the second box register value:\newline
\verb$\reuseb$ \the\reuseb\newline
\verb$\free@box2$ \the\csname free@box2\endcsname
\makeatother
\end{document}