Perl - 更改传递给子的父引用

时间:2016-01-20 16:01:40

标签: perl

我是perl的新手,无法找到有关我的问题的任何信息,所以如果这是重复或我完全出去吃午饭,请提前道歉。

实际问题略低一些。

#!/usr/bin/perl

use strict;
my @root = undef;
myfunc(\@root);

sub myfunc()
{
    my ($ptr_parent) = @_;
    print "root => ";
    print \@root;
    print "\n";
    print "ptr_parent => $ptr_parent\n";
    my @stuff = split(',', 'test1,test2,test3');
    $ptr_parent = \@stuff;
    print "stuff => ";
    print \@stuff;
    print "\n";
    print "root => ";
    print \@root;
    print "\n";
    print "ptr_parent => $ptr_parent\n";    
}

毫不奇怪,我的输出如下:

root => ARRAY(0x7f903182e890)
ptr_parent => ARRAY(0x7f903182e890)
stuff => ARRAY(0x7f9031838548)
root => ARRAY(0x7f903182e890)
ptr_parent => ARRAY(0x7f9031838548)

我想要实现的目标如下:

root => ARRAY(0x7f903182e890)
ptr_parent => ARRAY(0x7f903182e890)
stuff => ARRAY(0x7f9031838548)
root => ARRAY(0x7f9031838548)   <---- Note this changes.
ptr_parent => ARRAY(0x7f9031838548)

所以我怀疑这样做是不可能的,因为我想象@stuff内存指针会被释放。

我觉得我可以让@root成为$ root,它是指向指针的指针。但我仍然坚持如何写这个。指针的语法仍然不是100%。

但一般要求是,在myfunc中生成的任何列表都需要在@root中生存。我无法直接从myfunc();

修改@root

提前致谢。如果我需要澄清,请告诉我。

3 个答案:

答案 0 :(得分:3)

在您的代码中,$ptr_parent是一个包含引用的变量,您正在修改变量,而不是 referent 。如果要修改引用指向的实际内容,则需要使用一些取消引用语法。有关详细信息,请参阅perlreftut;有关所有详细信息,请参阅perlref

use strict;
use warnings;

use Data::Dump;

my @arr;
dd(\@arr);

foo(\@arr);
dd(\@arr);

bar(\@arr);
dd(\@arr);

sub foo {
    my $aref = shift;
    @$aref = split(/,/, 'test1,test2,test3');  # notice the dereference
}

sub bar {
    my $aref = shift;
    $aref->[0] = 42;  # individual element dereference
    $aref->[1] = 'ponies';
}

输出:

[]
["test1", "test2", "test3"]
[42, "ponies", "test3"]

答案 1 :(得分:2)

Perl通过引用传递,这意味着更改sub中的参数也会在调用者中更改它。但是你没有修改参数($_[0]);你正在修改一个词法变量($ptr_parent)。

以下所有内容适用于myfunc($root)

# Create the object as needed, and pass it back explicitly on exit.
sub myfunc {
    my $parent = $_[0] // [];
    push @$parent, split(/,/, 'test1,test2,test3');
    $_[0] = $parent;
}

# Create the object, and pass it back explicitly up front.
sub myfunc {
    my $parent = shift //= [];
    push @$parent, split(/,/, 'test1,test2,test3');
}

# Create the object as needed by using a layer of indirection.
sub myfunc {
    my $parent_ref = \shift;
    push @{ $$parent_ref }, split(/,/, 'test1,test2,test3');
}

或者你可能不那么“神奇”并传递对myfuncmyfunc(\$root))的引用:

sub myfunc {
    my $parent_ref = shift;
    push @{ $$parent_ref }, split(/,/, 'test1,test2,test3');
}

顺便说一句,原型是不正确的。我通过删除它解决了这个问题。

答案 2 :(得分:-1)

确实,您需要使用引用,并且如果要从其他位置修改引用,则传递对该引用的引用。

#!/usr/bin/perl

use strict;
my $root = [];
myfunc(\$root);

sub myfunc()
{
    my ($ptr_parent) = @_;
    print "root => ";
    print $root;
    print "\n";
    print "ptr_parent => $$ptr_parent\n";
    my @stuff = split(',', 'test1,test2,test3');
    $$ptr_parent = \@stuff;
    print "stuff => ";
    print \@stuff;
    print "\n";
    print "root => ";
    print $root;
    print "\n";
    print "ptr_parent => $$ptr_parent\n";
}

输出:

root => ARRAY(0x7f8143001ee8)
ptr_parent => ARRAY(0x7f8143001ee8)
stuff => ARRAY(0x7f8143022ad8)
root => ARRAY(0x7f8143022ad8)
ptr_parent => ARRAY(0x7f8143022ad8)