Perl字符串是不可变的吗?

16

当我对一个字符串进行连接操作时,背后会发生什么?

my $short = 'short';
$short .= 'cake';

Perl是否实际上创建了一个新字符串,然后将正确的变量引用分配给它,还是Perl字符串天生可变?

这个问题的动机来自我与同事的讨论,他说脚本语言可以利用不可变字符串。


如果在 perldoc 中有任何可靠的参考资料,将不胜感激。 - Zaid
可能对一些人来说,坚实的参考文献 太过坚实了:请查看 perldoc perlguts 并在 SvGROW 附近寻找。否则,@eugene 的回答就是你要找的。 - Dummy00001
perlfunc文档中的substr(作为lvalue和4个参数调用)描述了修改字符串本身的操作:增长、缩小和替换部分。 - pilcrow
3个回答

20

Perl字符串可变的。如果需要,Perl会自动创建新缓冲区。

use Devel::Peek;
my $short = 'short';

Dump($short);
Dump($short .= 'cake');
Dump($short = "");

SV = PV(0x28403038) at 0x284766f4
  REFCNT = 1
  FLAGS = (PADMY,POK,pPOK)
  PV = 0x28459078 "short"\0
  CUR = 5
  LEN = 8
SV = PV(0x28403038) at 0x284766f4
  REFCNT = 1
  FLAGS = (PADMY,POK,pPOK)
  PV = 0x28458120 "shortcake"\0
  CUR = 9
  LEN = 12
SV = PV(0x28403038) at 0x284766f4
  REFCNT = 1
  FLAGS = (PADMY,POK,pPOK)
  PV = 0x28458120 ""\0
  CUR = 0
  LEN = 12
请注意,第三种情况下不会分配新的缓冲区。

2
Perl使用realloc,这可能会或可能不会获得一个全新的缓冲区。 - ysth
请注意,即使Perl不使用它来确定长度,它仍然为尾随的nul分配空间。 还要注意,无论在哪里可能,它都知道malloc库的粒度,并将分配舍入到较高的位置。 - ysth

12

Perl字符串肯定是可变的。除了使用长度和开始偏移量外,每个字符串都将存储分配的缓冲区大小,并且缓冲区将根据需要进行扩展。(开始偏移量对于允许像s/^abc//这样的消耗性操作不必移动实际数据非常有用。)


1
perldoc 中是否有对此的硬引用? - Zaid
@Zaid:我目前不知道。 - ysth

0
$short = 'short';
print \$short;

$short .= 'cake';
print \$short;

执行此代码后,我得到了“SCALAR(0x955f468)SCALAR(0x955f468)”。我的答案将是“可变的”。

7
Perl的标量实际上由两个不同的部分组成:一个是固定大小的,另一个是可选的、根据存储的值类型而变化大小的。此处的地址是固定大小组件的地址;可变大小组件完全有可能被替换为新组件。但事实上并非如此。 :) - ysth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接