Learning Perl Objects, References amp;amp; Modules [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Learning Perl Objects, References amp;amp; Modules [Electronic resources] - نسخه متنی

Randal L. Schwartz

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید














4.3 Reference Counting and Nested Data Structures


The data remains alive until the last
reference is destroyed, even if that reference is contained within a
larger active data structure. Suppose an array element is itself a
reference. Recall the example from Chapter 3:

my @skipper = qw(blue_shirt hat jacket preserver sunscreen);
my @skipper_with_name = ("The Skipper", \@skipper);
my @professor = qw(sunscreen water_bottle slide_rule batteries radio);
my @professor_with_name = ("The Professor", \@professor);
my @gilligan = qw(red_shirt hat lucky_socks water_bottle);
my @gilligan_with_name = ("Gilligan", \@gilligan);
my @all_with_names = (
\@skipper_with_name,
\@professor_with_name,
\@gilligan_with_name,
);

Imagine for a moment that the intermediate variables are all part of
a subroutine:

my @all_with_names;
sub initialize_provisions_list {
my @skipper = qw(blue_shirt hat jacket preserver sunscreen);
my @skipper_with_name = ("The Skipper", \@skipper);
my @professor = qw(sunscreen water_bottle slide_rule batteries radio);
my @professor_with_name = ("The Professor", \@professor);
my @gilligan = qw(red_shirt hat lucky_socks water_bottle);
my @gilligan_with_name = ("Gilligan", \@gilligan);
@all_with_names = ( # set global
\@skipper_with_name,
\@professor_with_name,
\@gilligan_with_name,
);
}
initialize_provisions_list( );

The value of @all_with_names is set to contain
three references. Inside the subroutine are named arrays with
references to arrays first placed into other named arrays.
Eventually, the values end up in the global
@all_with_names. However, as the subroutine
returns, the names for the six arrays disappear. Each array has had
one other reference taken to it, making the reference count
temporarily two, and then back to one as the name is removed. Because
the reference count is not yet zero, the data continues to live on,
although it is now referenced only by elements of
@all_with_names.

Rather than assign the global variable, you can rewrite this as:

sub get_provisions_list {
my @skipper = qw(blue_shirt hat jacket preserver sunscreen);
my @skipper_with_name = ("The Skipper", \@skipper);
my @professor = qw(sunscreen water_bottle slide_rule batteries radio);
my @professor_with_name = ("The Professor", \@professor);
my @gilligan = qw(red_shirt hat lucky_socks water_bottle);
my @gilligan_with_name = ("Gilligan", \@gilligan);
return (
\@skipper_with_name,
\@professor_with_name,
\@gilligan_with_name,
);
}
my @all_with_names = get_provisions_list( );

Here, you create the value that will eventually be stored into
@all_with_names as the last expression evaluated
in the subroutine. A three-element list is returned and assigned. As
long as the named arrays within the subroutine have had at least one
reference taken of them, and it is still part of the return value,
the data remains alive.[1]

[1] Compare this with having to
return an array from a C function. Either a pointer to a static
memory space must be returned, making the subroutine nonreentrant, or
a new memory space must be
malloc'ed, requiring the caller
to know to free the data. Perl just does the right
thing.


If the references in @all_with_names are altered
or discarded, the reference count for the corresponding arrays is
reduced. If that means the reference count has become zero (as in
this example), those arrays themselves are also eliminated. Because
these arrays also contain a reference (such as the reference to
@skipper), that reference is also reduced by one.
Again, that reduces the reference count to zero, freeing that memory
as well, in a cascading effect.

Removing the top of a tree of data generally removes all the data
contained within. The exception is when additional copies are made of
the references of the nested data. For example, if you copied
Gilligan's provisions:

my $gilligan_stuff = $all_with_names[2][1];

then when you remove @all_with_names, you still
have one live reference to what was formerly
@gilligan, and the data from there downward
remains alive.

The bottom line is simply: Perl does the right thing. If you still
have a reference to data, you still have the data.



/ 199