为什么对指向 `substr` 的引用调用 `ref` 时会得到“LVALUE”?

编程语言 2026-07-09

我在处理一些代码,这段代码创建了对子字符串调用的引用,然后把它传递出去。我原以为这会是一个 SCALAR 引用,因为它看起来就像在其中放入一个字符串后再返回一个 SCALAR?为什么这个 ref 会返回 LVALUE

use strict;
use warnings;
use feature 'say';

my $str = "hello";
my $lv = \substr($str, 1, 2);
say ref($lv);          # LVALUE

我在 perlguts 里做了一点研究,确实看到了 LVALUE SVTYPE,所以我认为这是预期的行为。

解决方案

使用 \substr(...) 时,你确实对一个可修改的内存位置取了引用,因为 substr() 是一个左值函数,而你的 $lv 会输出 LVALUE(memory-location)LVALUE 是一种特殊类型标量的引用,因此 ref(和 Scalar::Util::reftype)返回该标签。该内存位置包含了 substr(...) 本应返回的内容。

当你打印 $$lv 时,你得到的是 substr() 调用返回的结果;如果你给 $$lv 赋值,原始字符串中相应的字符范围会被修改(因为 substr 是一个可以作为左值使用的函数)。

一个命令行程序(“单行命令”)作为示例:

perl -wE'$s = "hello"; $lv = \substr($s, 1, 2); say $lv; say $$lv; 
         $$lv = "WHOA"; say $s'

(为便于阅读,我把它分成两行。用Bash仍然可以直接复制粘贴到终端)

它输出

LVALUE(0x55d494b604d8)
el
hWHOAlo

一旦在 $lv 中获得那条 LVALUE 引用,我们就可以继续使用它——对 $$lv 的进一步写入会改变 原始 字符串

perl -wE'$s = "hello"; $lv = \substr($s, 1, 2); 
         for (qw(WHOA A OHYES)) { $$lv = $_; say $s }'

输出

hWHOAlo
hAlo
hOHYESlo
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章