Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.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_Oop_Destructor_Weak References - Fatal编程技术网

Perl 具有强引用的对象在引用超出范围之前被销毁?

Perl 具有强引用的对象在引用超出范围之前被销毁?,perl,oop,destructor,weak-references,Perl,Oop,Destructor,Weak References,我有以下Perl代码: #!/usr/bin/perl use strict; use warnings; # Parent object package Parent; { use Moose; has 'children' => (is => 'rw', isa => 'ArrayRef[Child]', default => sub { [] }); } # Child object package Child; { use Moose

我有以下Perl代码:

#!/usr/bin/perl
use strict;
use warnings;

# Parent object
package Parent;
{
    use Moose;

    has 'children' => (is => 'rw', isa => 'ArrayRef[Child]', default => sub { [] });
}

# Child object
package Child;
{
    use Moose;

    has 'parent' => (is => 'ro', isa => 'Parent', required => 1);

    # Child DEMOLISHER!!!! >:)
    sub DEMOLISH {
        my ($self) = @_;

        # Loop through the known children of the parent
        for my $index (0 .. $#{$self->parent->children()}) {

            # Remove the destroyed child
            if ($self->parent->children->[$index] == $self) {
                splice @{$self->parent->children()}, $index, 1;
                return;
            }
        }
    }
}

package Test;
{
    use Scalar::Util qw(weaken);
    use Data::Dumper;

    # Create a parent object
    my $parent = Parent->new();
    {
    
        # Create children (with STRONG refs to the parent)
        my $child  = Child->new('parent' => $parent);
        my $child2 = Child->new('parent' => $parent);
        my $child3 = Child->new('parent' => $parent);

        # Add children to the parents list of children
        push @{$parent->children()}, ($child, $child2, $child3);

        # Weaken the last childref
        weaken($parent->children->[-1]);

        # Print the children
        print Dumper($parent->children());
    }

    # The weakened child is out of scope and should be removed
    print Dumper($parent->children());
}
此代码创建一个父对象,然后创建3个子对象(每个子对象都具有对父对象的强引用)。然后一个孩子被削弱了。当孩子们超出范围时,预计虚弱的孩子将被销毁并从父母的
孩子
数组中移除(哇,听起来很残忍),而其他两个孩子则会留下

但是,运行此代码后,我得到以下输出:

使用以下错误消息:

在全局销毁期间在第28行的数字等式(=)中使用未初始化值。

(在清理中)无法在全局销毁期间对第25行的未定义值调用方法“children”。

现在要澄清这个错误

第25行是这一行:
用于我的$index(0..${$self->parent->children()}{

它无法调用
$self->parent()
!(这可以通过尝试打印
$self->parent()的值来测试)


该错误似乎表明在父对象已销毁之后正在销毁子对象,因此父对象现在未定义。但是正在销毁的子对象包含对父对象的引用,因此在子对象被销毁之前不应允许销毁父对象耶德


这是怎么回事?

我不太明白你想说什么?代码是有效的,我只是想知道为什么它声称父对象不再存在。它不应该允许父对象被销毁,直到所有子对象都被销毁。实际上,其他两个子对象也不应该被销毁,因为父对象包含strong对这两个对象的引用。您有一个内存引用周期导致内存泄漏。但是泄漏的对象仍然在程序退出时被释放。但是由于它们没有被正确释放,它们可能不会按照您期望的顺序被释放。@ikegami,您是说因为父对象引用子对象,而2个非弱子对象引用pa吗请注意,Perl不知道在脚本末尾首先销毁哪一个,所以它只选择了一个?我没有研究代码来确定泄漏是什么,但是您的对象在声明词汇表的块结束后仍然存在,因为它们在全局销毁期间被释放,而全局销毁是在文件完成之后发生的正在执行。{$parent->children()}
会更惯用。
map
的预期用途是将一个列表转换为另一个列表。我不完全明白你想说什么?代码是有效的。我只是想知道为什么它声称父对象不再存在。它不应该允许父对象被销毁,直到所有的子对象都被销毁。实际上e其他2个子对象也不应被销毁,因为父对象包含对它们的强引用。您有一个内存引用周期,导致内存泄漏。但是泄漏的对象仍然在程序退出时被释放。但是由于它们没有被正确释放,它们可能不会按您期望的顺序被释放。@ikegami,您是说since父级引用子级,2个非弱子级引用父级,Perl在脚本末尾不知道首先销毁哪一个,所以它只选择了一个?我没有研究代码来确定泄漏是什么,但是您的对象在声明词典的块末尾仍然存在,因为它们是在全局销毁期间获得释放,这发生在文件完成执行之后。弱化($)@{$parent->children()};将更为惯用。
map
的预期用途是将一个列表转换为另一个列表。