【问题标题】:What is the magic behind perl read() function and buffer which is not a ref?perl read() 函数和不是 ref 的缓冲区背后的魔力是什么?
【发布时间】:2011-03-01 23:57:18
【问题描述】:

我不明白 Perl 的 read($buf) 函数如何能够修改 $buf 变量的内容。 $buf 不是参考,因此参数由副本给出(根据我的 c/c++ 知识)。那么 $buf 变量是如何在调用者中被修改的呢?

它是一个关系变量还是什么?关于 setbuf 的 C 文档对我来说也非常难以捉摸和不清楚

# Example 1
$buf=''; # It is a scalar, not a ref
$bytes = $fh->read($buf);
print $buf; # $buf was modified, what is the magic ?

# Example 2
sub read_it {
    my $buf = shift;
    return $fh->read($buf);
}
my $buf;
$bytes = read_it($buf);
print $buf; # As expected, this scope $buf was not modified

【问题讨论】:

    标签: perl io buffer handle


    【解决方案1】:

    不需要任何魔法——如果你愿意,所有的 perl 子例程都是通过别名调用的。阔思perlsub:

    数组@_ 是一个本地数组,但它的元素是别名 对于实际的标量参数。特别是,如果一个元素 $_[0] 更新了,对应的参数也更新了(或者出现错误 如果它不可更新)。

    例如:

    sub increment {
      $_[0] += 1;
    }
    
    my $i = 0;
    increment($i);  # now $i == 1
    

    在您的“示例 2”中,您的 read_it复制 @_ 的第一个元素到词法 $buf,然后通过调用“就地”修改该副本read()。传入$_[0]而不是复制,看看会发生什么:

    sub read_this {
      $fh->read($_[0]);  # will modify caller's variable
    }
    sub read_that {
      $fh->read(shift);  # so will this...
    }
    

    【讨论】:

    • 非常感谢您提供指向相关文档的指针,您的技巧奏效了,非常感谢
    【解决方案2】:

    read() 是一个内置函数,因此可以发挥作用。不过,您可以通过声明 function prototype 来使用自己的函数完成类似的操作:

    sub myread(\$) { ... }
    

    参数声明\$ 表示该参数作为引用被隐式传递。

    内置 read 的唯一魔力在于它即使在间接调用或作为文件句柄方法时也能正常工作,这对常规函数不起作用。

    【讨论】:

    • 您不需要原型或显式传递引用来修改传递给子例程的变量:sub foo { $_[0] ++ }
    • +1 对于 OP 的问题,这并不完全正确,但是在这个领域中了解原型和 真正 perl 引用(不是符号引用)很重要。
    • @FM,很好。我总是忘记@_可以这样使用。
    猜你喜欢
    • 1970-01-01
    • 2012-05-15
    • 2012-11-30
    • 2011-04-02
    • 2010-09-24
    • 1970-01-01
    • 2018-02-08
    • 2018-12-14
    • 1970-01-01
    相关资源
    最近更新 更多