Perl   发布时间:2022-04-07  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了在perl中,当将子例程的返回值赋给变量时,数据是否在内存中重复?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
sub foo {
    my @return_value = (1,2);
}
my @receiver = foo();
@H_944_4@这个分配是否像perl中的任何其他分配一样?数组在内存中重复?我怀疑这个原因,因为子程序保存的数组是一次性的,复制完全是多余的.为了优化原因,将数组“链接”到@receiver是有意义的.

@H_944_4@顺便说一句,我注意到类似的问题@L_944_0@,但没有得到我想要的.

@H_944_4@而我在谈论Perl5

@H_944_4@Ps.关于perl这类主题的任何书籍或材料?

解决方法

返回的标量:lvalue subs不会被复制. @H_944_4@XS subs返回的标量不会被复制.

@H_944_4@函数返回的标量(命名运算符)不会被复制.

@H_944_4@其他潜艇返回的标量被复制.

@H_944_4@但那是在任何任务发挥作用之前.如果将返回的值分配给变量,则将复制它们(同样,在普通Perl sub的情况下).

@H_944_4@这意味着我的$y = sub {$x} – >();复制$x两次!

@H_944_4@但由于优化,这并不重要.

@H_944_4@让我们从一个未复制它们的例子开始.

$perl -le'
    sub f :lvalue { my $x = 123; print \$x; $x }
    my $r = \f();
    print $r;
'
SCALAR(0x465eb48)  # $x
SCALAR(0x465eb48)  # The scalar on the stack
@H_944_4@但如果你删除:左值…

$perl -le'
    sub f { my $x = 123; print \$x; $x }
    my $r = \f();
    print $r;
'
SCALAR(0x17d0918)  # $x
SCALAR(0x17b1ec0)  # The scalar on the stack
@H_944_4@更糟糕的是,人们通常会通过将标量指定给变量来进行跟进,因此会出现第二个副本.

$perl -le'
    sub f { my $x = 123; print \$x; $x }
    my $r = \f();   # \
    print $r;       #  > my $y = f();
    my $y = $$r;    # /
    print \$y;
'
SCALAR(0x1802958)  # $x
SCALAR(0x17e3eb0)  # The scalar on the stack
SCALAR(0x18028f8)  # $y
@H_944_4@从好的方面来说,优化分配以最小化复制字符串的成本.

@H_944_4@XS subs和函数(命名运算符)通常返回凡人(“TEMP”)标量.这些是“死囚牢房”中的标量.如果没有任何步骤声明对它们的引用,它们将被自动销毁.

@H_944_4@在旧版本的Perl(< 5.20)中,将凡人字符串分配给另一个标量将导致字符串缓冲区的所有权被转移以避免必须复制字符串缓冲区.例如,我的$y = lc($X);不复制lc创建的字符串;只需复制字符串指针.

$perl -MDevel::Peek -e'my $s = "abc"; Dump($s); $s = lc($s); Dump($s);'
SV = PV(0x1705840) at 0x1723768
  REFCNT = 1
  FLAGS = (PADMY,POK,IsCOW,pPOK)
  PV = 0x172d4c0 "abc"\0
  CUR = 3
  LEN = 10
  COW_REFCNT = 1
SV = PV(0x1705840) at 0x1723768
  REFCNT = 1
  FLAGS = (PADMY,pPOK)
  PV = 0x1730070 "abc"\0     <-- Note the change of address from stealing
  CUR = 3                        the buffer from the scalar returned by lc.
  LEN = 10
@H_944_4@在较新版本的Perl(≥5.20)中,赋值运算符永远不会[1]复制字符串缓冲区.相反,较新版本的Perl使用写时复制(“COW”)机制.

$perl -MDevel::Peek -e'my $x = "abc"; my $y = $x; Dump($X); Dump($y);'
SV = PV(0x26b0530) at 0x26ce230
  REFCNT = 1
  FLAGS = (POK,pPOK)
  PV = 0x26d68a0 "abc"\0            <----+
  CUR = 3                                |
  LEN = 10                               |
  COW_REFCNT = 2                         +-- Same buffer (0x26d68a0)
SV = PV(0x26b05c0) at 0x26ce248          |
  REFCNT = 1                             |
  FLAGS = (POK,pPOK)               |
  PV = 0x26d68a0 "abc"\0            <----+
  CUR = 3
  LEN = 10
  COW_REFCNT = 2
@H_944_4@好吧,到目前为止,我只讨论过标量.嗯,这是因为Subs和函数只能返回标量[2].

@H_944_4@在您的示例中,分配给@return_value的标量将被返回[3],复制,然后通过赋值再次复制到@receiver.

@H_944_4@您可以通过返回对数组的引用来避免所有这些.

sub f { my @fizbobs = ...; \@fizbobs }
my $fizbobs = f();
@H_944_4@复制的唯一东西是引用,最简单的非undefined标量.

@H_944_4@>好吧,也许永远不会.我认为字符串缓冲区中需要有一个空闲字节来保存COW计数.
>在列表上下文中,它们可以返回0,1或多个,但它们只能返回标量.
> sub的最后一个运算符是列表赋值运算符.在列表上下文中,列表赋值运算符返回其左侧(LHS)计算的标量.有关详细信息,请参阅Scalar vs List Assignment Operator.

大佬总结

以上是大佬教程为你收集整理的在perl中,当将子例程的返回值赋给变量时,数据是否在内存中重复?全部内容,希望文章能够帮你解决在perl中,当将子例程的返回值赋给变量时,数据是否在内存中重复?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。