When I dereference an array using @$arrayRef or @{$arrayRef} it appears to create a copy of the array. Is there a correct way to dereference an array?
This code...
sub updateArray1 {
my $aRef = shift;
my @a = @$aRef;
my $aRef2 = \@a;
$a[0] = 0;
push(@a, 3);
my $aRef3 = \@a;
print "inside1 \@a: @a\n";
print "inside1 \$aRef: $aRef\n";
print "inside1 \$aRef2: $aRef2\n";
print "inside1 \$aRef3: $aRef3\n\n";
}
my @array = (1, 2);
print "before: @array\n";
my $ar = \@array;
print "before: $ar\n\n";
updateArray1(\@array);
print "after: @array\n";
$ar = \@array;
print "after: $ar\n\n";
... has the output...
before: 1 2
before: ARRAY(0x1601440)
inside1 @a: 0 2 3
inside1 $aRef: ARRAY(0x1601440)
inside1 $aRef2: ARRAY(0x30c1f08)
inside1 $aRef3: ARRAY(0x30c1f08)
after: 1 2
after: ARRAY(0x1601440)
As you can see, @$aRef creates a new pointer address.
The only way I've found to get around this is to only use the reference:
sub updateArray2 {
my $aRef = shift;
@$aRef[0] = 0;
push(@$aRef, 3);
print "inside2 \@\$aRef: @$aRef\n";
print "inside2 \$aRef: $aRef\n\n";
}
updateArray2(\@array);
print "after2: @array\n";
$ar = \@array;
print "after2: $ar\n\n";
Which produces the output:
inside2 @$aRef: 0 2 3
inside2 $aRef: ARRAY(0x1601440)
after2: 0 2 3
after2: ARRAY(0x1601440)
Is it possible to dereference a pointer to an array without the whole array getting duplicated? Or do I need to keep it in reference form and dereference it any time I want to use it?
Dereferencing an array It is done by placing the @ symbol (the sigil representing arrays) in-front of the reference. This can be written either wrapped in curly braces: @{$names_ref} or without the curly braces: @$names_ref.
You cannot dereference an array, only a pointer. What's happening here is that an expression of array type, in most contexts, is implicitly converted to ("decays" to) a pointer to the first element of the array object. So ar "decays" to &ar[0] ; dereferencing that gives you the value of ar[0] , which is an int .
Dereferencing in Perl returns the value from a reference point to the location. To dereference a reference simply use $, @ or % as a prefix of the reference variable depending on whether the reference is pointing to a scalar, array, or hash.
In order to dereference, we use the prefix $, @, % or & depending on the type of the variable(a reference can point to a array, scalar, or hash etc).
Dereferencing does not create a copy as can be seen in the following example:
my @a = qw(a b c);
my $ra = \@a;
@{$ra}[0,1] = qw(foo bar); # dereferencing is done here but not copying
print @$ra; # foo bar c
print @a; # foo bar c
Instead, assigning the (dereferenced) array to another array creates the copy:
my @a = qw(a b c);
my $ra = \@a;
my @newa = @$ra; # copy by assigning
$newa[0] = 'foo';
print @newa; # foo b c
print @a; # a b c
Assigning one array to another says essentially that all elements from the old array should be assigned to the new array too - which is different from just having a different name for the original array. But assigning one array reference to another just makes the old array available with a different name, i.e. copy array reference vs. copy array content.
Note that this seems to be different to languages like Python or Java because in these languages variables describe array objects only, i.e. the reference to the array and not the content of the array.
Using the experimental refaliasing feature:
use 5.022;
use warnings;
use feature 'refaliasing';
no warnings 'experimental::refaliasing';
\my @array = $array_ref;
But why not just keep it as a reference? There's nothing you can do with an array that you can't also do with an array reference.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With