Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 分配子例程的结果是否会产生数据的副本?_Perl_Reference_Pass By Value - Fatal编程技术网

Perl 分配子例程的结果是否会产生数据的副本?

Perl 分配子例程的结果是否会产生数据的副本?,perl,reference,pass-by-value,Perl,Reference,Pass By Value,我试图理解赋值子程序的结果是否会导致数据的复制 sub maketext { 'text' }; my $foo = maketext(); my $foo_ref = \$foo; my $bar_ref = \maketext(); 在上述示例中,创建$foo\u ref是否会比创建$bar\u ref多产生一份副本 我怎样才能使自己相信它们是等效的还是不等效的?数据拷贝似乎发生了 sub maketext { my $text = 'text'; say \$text

我试图理解赋值子程序的结果是否会导致数据的复制

sub maketext { 'text' };

my $foo = maketext();
my $foo_ref = \$foo;

my $bar_ref = \maketext();
在上述示例中,创建
$foo\u ref
是否会比创建
$bar\u ref
多产生一份副本


我怎样才能使自己相信它们是等效的还是不等效的?

数据拷贝似乎发生了

sub maketext {
    my $text = 'text';
    say \$text;
    return $text;
}

my $bar_ref = \maketext();
say $bar_ref;
这张照片

SCALAR(0x11f5818) SCALAR(0x11cfa68) 或者使用
do{\my$var}
,或者在您的情况下使用sub

sub anon_scalar_ref {
    # ...
    return \my $var;
}
然而,我看不出你有什么用。也许你想做什么

sub maketext {
    # ... define $text ...
    return \$text;
}
当您将此返回赋值给变量时,不会进行额外的数据复制,因为返回的是引用。

Perl必须复制数据。否则,对变量
$foo
的任何后续修改都将试图修改字符串常量
'text'
,这将导致代码失效

这就是中国发生的事情

for ( 'text' ) {
    $_ = 'test';
}
这就产生了错误

试图修改只读值

是的,它是复制品

use Devel::Peek qw( Dump );

sub maketext {
    my $text = 'text';
    Dump($text);
    return $text;
}

my $ref = \maketext();
Dump($$ref);
输出:

SV = PV(0x8b18a0) at 0x8dbe38   <-- $text is at 0x8dbe38
  REFCNT = 1
  FLAGS = (POK,IsCOW,pPOK)
  PV = 0x8d9f70 "text"\0        <-- String buffer at 0x8d9f70
  CUR = 4
  LEN = 10
  COW_REFCNT = 1
SV = PV(0x8b1920) at 0x8b0cc8   <-- $$ref is at 0x8b0cc8
  REFCNT = 1
  FLAGS = (POK,IsCOW,pPOK)
  PV = 0x8d9f70 "text"\0        <-- String buffer at 0x8d9f70
  CUR = 4
  LEN = 10
  COW_REFCNT = 1
SV = PV(0xe43c80) at 0xe6e238
[...]
SV = PV(0xe43c80) at 0xe6e238
[...]
输出:

SV = PV(0x8b18a0) at 0x8dbe38   <-- $text is at 0x8dbe38
  REFCNT = 1
  FLAGS = (POK,IsCOW,pPOK)
  PV = 0x8d9f70 "text"\0        <-- String buffer at 0x8d9f70
  CUR = 4
  LEN = 10
  COW_REFCNT = 1
SV = PV(0x8b1920) at 0x8b0cc8   <-- $$ref is at 0x8b0cc8
  REFCNT = 1
  FLAGS = (POK,IsCOW,pPOK)
  PV = 0x8d9f70 "text"\0        <-- String buffer at 0x8d9f70
  CUR = 4
  LEN = 10
  COW_REFCNT = 1
SV = PV(0xe43c80) at 0xe6e238
[...]
SV = PV(0xe43c80) at 0xe6e238
[...]

即使考虑在这里花费的时间也是一个巨大的错误。您应该考虑哪个代码更可读。如果你的结果是如此巨大,以至于复制确实产生了真正的影响,你应该返回一个参考。“过早的优化是万恶之源”。想都别想,这都是小事。除非它不是,但为此你使用了一个代码分析器。它不一定是微观优化。我不知道答案,我很想知道它是什么,只是因为。上下文:我正在使用一个名为
WWW::Mechanize::content
的函数,并将结果传递给另一个函数。我想知道我是否写了
我的$content\u ref=\$mech->content;foo($content\u ref)
my$content=$mech->content;foo(\$content)产生了影响,纯粹是出于兴趣。现在我了解到后者将复制标量,但不会复制基础数据,因此差异可以忽略不计。您的第一句话是“是的,它复制了”,但在阅读了您答案的COW部分后,我的问题中“数据”的定义似乎需要更具体。从这个答案中,我了解到标量是被复制的,而不是底层字符串缓冲区(直到值被修改)。我从左值子函数中注意到,尽管它避免了复制,但每次调用它都会创建一个新的标量(仍然使用相同的PV),而非左值版本重用相同的变量。
my
变量确实在可能的情况下被重用(在子函数退出时确定)。如果一个
my
变量是从一个左值子变量返回的,那么显然不可能重用它。请注意,COW是相对较新的,但在此之前还有另一个优化:从TEMP窃取缓冲区。这意味着,如果从sub返回的是“临时”,则其缓冲区将“被盗”,而不是复制。临时值是一个构造值(例如,从串联、substr等获得的值)。