cammac has asked for the wisdom of the Perl Monks concerning the following question:

If I have stored an array reference in a structure, and then add values to the array (suppose the array has to be 'moved' in memory to expand for the additional values), will the array reference be automatically updated in my structure, or will I need to do that manually? Thank you for the answer! In C, I can look at the assembly code to determine what the compiled code is doing, but I don't have the luxury of doing that with Perl and I'm not experienced enough to have built up the experience required to have a better understanding of how things work in Perl.

Replies are listed 'Best First'.
Re: array reference
by ikegami (Patriarch) on Aug 22, 2007 at 15:14 UTC

    Yes, it's safe. There is an (invisible) indirection layer that also contains info such as the size of the array.

    By the way, adding or removing elements from the front or back of the array doesn't cause a reallocation, so those operations are very efficient.

Re: array reference
by akho (Hermit) on Aug 22, 2007 at 15:13 UTC
    It will. It's not a C pointer, it only looks like one.
Re: array reference
by girarde (Hermit) on Aug 22, 2007 at 17:20 UTC
    Executive summary: it's automatic.

    The array reference will not change; it will continue to refer to the array, which will now contain the new values. Sort of like the market's address doesn't change when they add Weetabix to the cereal section.

Re: array reference
by liverpole (Monsignor) on Aug 22, 2007 at 15:16 UTC
    Hi cammac,

    Why not just try it? ...

    use strict; use warnings; use Data::Dumper; my $parray = [ qw( a b c ) ]; printf "Array before change is: %s\n", Dumper($parray); my $phash = { 'array' => $parray, }; printf "Hash before change is: %s\n", Dumper($phash); push @$parray, 'd', 'e', 'f'; printf "Array after change is: %s\n", Dumper($parray); printf "Hash after change is: %s\n", Dumper($phash);

    The results indicate that you do NOT need to do anything manually:

    Array before change is: $VAR1 = [ 'a', 'b', 'c' ]; Hash before change is: $VAR1 = { 'array' => [ 'a', 'b', 'c' ] }; Array after change is: $VAR1 = [ 'a', 'b', 'c', 'd', 'e', 'f' ]; Hash after change is: $VAR1 = { 'array' => [ 'a', 'b', 'c', 'd', 'e', 'f' ] };

    s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/

      Not everything can be answered by "try it and see". This is one of those cases where TIAS doesn't work. More importantly, someone asking that question surely knows that (since realloc can return the same pointer it was passed).

      You'll also get a false positive if Perl preallocates more space than it needs (and it does) and the array size is grown insufficiently.

      Your test didn't proove anything.

Re: array reference
by blue_cowdawg (Monsignor) on Aug 22, 2007 at 15:14 UTC
        If I have stored an array reference in a structure, and then add values to the array.....

    not sure what that meant. Can you post some code to show exactly what you are attempting to do?


    Peter L. Berghold -- Unix Professional
    Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg

      In C, resizing an array invalidates existing pointers to the array.

      int* a; a = (int*)malloc(...); int* b = a; a = (int*)realloc(a, ...); /* b now contains garbage */

      The OP was asking if the same happens in Perl.

      my @array; my $aref = \@array; push @array, ...; # Is $aref still valid? Yes.
            In C, resizing an array invalidates existing pointers to the array.

        Now that you put it that way, I understand what was being asked.

        While I can't cite which source code in core Perl it is I know I've seen how it is handled and I definitely agree with your assesment.

        Writing sample code such as you've provided solidifies it.


        Peter L. Berghold -- Unix Professional
        Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg