togatttiのエンジニアメモ

過度な期待はしないでください。旧麹町で働くエンジニアのメモ帳です。

Perlのリファレンス、デリファレンス入門

前提

PerlのプログラムはCPUメモリの中で動作する。

値を入れた変数や特定の処理を保持したサブルーチンなどのデータはメモリ領域上のどこかに保存される。

リファレンスとは

メモリ領域の中のどこに変数やサブルーチンが保存されているかを示す場所情報、 メモリアドレスのことをリファレンス(参照)と呼ぶ。

メモリと変数に関する簡単な図を作った。

あくまで自分が理解するためのイメージ図である。

下記の1~9という領域全体がメモリ領域を示すと考える。

$fooと$hooと$barが格納されている5,7,9という番号がリファレンスである。

f:id:togattti1990:20140122081716p:plain

Perlにおけるリファレンスの取得方法

Perlではスカラー変数、リスト、ハッシュ、サブルーチンなど のリファレンスを下記のようにして取得する。

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

my $_hoge = "HOGE";
my @_hoge = qw( HOGE );
my %_hoge = qw(HOGE HOGE2);
sub hoge { return 1; }

print \$_hoge,"\n";
print \@_hoge,"\n";
print \%_hoge,"\n";
print \&hoge,"\n";

実行

$ perl reference.pl
SCALAR(0x21ac558)
ARRAY(0x21ac5b8)
HASH(0x21ac510)
CODE(0x21ac648)

メモリアドレスは一意な16進数形式の文字列で表現される。

デリファレンスする

デリファレンスとはリファレンスが指すデータの中身、内容を取得すること。

変数がメモリ領域のどこにおいてあるのかが分かれば、後はその場所を探すだけで内容がわかる。

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

my $_hoge = "HOGE";

# reference
my $r_hoge = \$_hoge;
print "ref:$r_hoge\n";

#dereference
print "deref:$$r_hoge\n";

実行する

$ perl dereference.pl
ref:SCALAR(0x1568558)
deref:HOGE

リストやハッシュ、サブルーチンではまた方法が違ってくるが、 ここでは入門知識だけ書きたいので、説明を省く。

参照渡し

サブルーチンへリファレンスを渡すことでサブルーチン内でデリファレンスして、データを扱うことができる。

ここで扱うデータは唯一のデータであるので、変更を加えればサブルーチンに渡す前のデータも変更される。

値渡しのように変数をコピーするわけではないので、メモリの無駄遣いを防ぐことができる。

参照渡しはこんな感じにする。

my $c = "hoge";
sub a {
  my $c1 = shift;
  print $$c1, "\n";
  }
sub b {
  my $c2 = shift;
  print $$c2, "\n";
  }
a(\$c);
b(\$c);

f:id:togattti1990:20140123073748p:plain

ちなみに値渡しだと。

my $c = "hoge";
sub a {
  my $c1 = shift;
  print \$c1, "\n";
  }
sub b {
  my $c2 = shift;
  print \$c2, "\n";
  }
print \$c;
a($c);
b($c);

実行する

SCALAR(0x7fa70a8286b8)
SCALAR(0x7fa70a828658)
SCALAR(0x7fa70a83b3f8)

変数が新しく作成されるため、参照が異なることが分かる。

f:id:togattti1990:20140123074554p:plain

参考:

08 - References

値渡しと参照渡しの違いを理解する