• ベストアンサー

リファレンスをサブルーチンの戻り値にしてもOKですか?

■ サブルーチン内部で処理した結果を格納した、配列、ハッシュ、スカラーなどのデータを戻り値として利用する必要があります。その場合、どうするのが標準的なやり方でしょうか? ■ return (配列へのリファレンス, ハッシュへのリファレンス, スカラー); などとやってしまっても問題はないでしょうか? ■ 下のプログラムを試したところ、予想に反しちゃんと 「31415」と表示されました。 #!/usr/bin/perl -w sub subroutine{ my @a = (3, 1, 4, 1, 5); return \@a; } my $b = subroutine{}; print @$b; ■ サブルーチン内部で使用した変数へのリファレンスをサブルーチン 外で使っていいのだろうか? サブルーチンの処理が終了した時点でサブルーチン内部で使用した 変数はメモリーから消去されるのかと思ったものですから。

  • Perl
  • 回答数2
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

サブルーチンの中でmy を使って宣言した変数であれば、 そのリファレンスを返しても問題ありません。 というのはそのような変数は、どこから参照されているかという 数を数えていて、それが0になったときに初めて実体が破棄されるからです。 >my @a = (3, 1, 4, 1, 5); ここで配列変数を作ってそれが @a なのでこの時点で参照数は1です。 > return \@a; > } ここで@aのリファレンスを\で取得してそれを返しているので +1 して参照数が2になります。 が、すぐにこのサブルーチンが終わるのでそこで-1されます。 結果として、参照数が1の状態でサブルーチンを抜けるので 実体は破棄されずに残り続けることになります。 Cなんかだと関数にローカルな変数のアドレスや参照を返すのは ご法度ですが、Perlはそうではないということです。 #Cでもstaticであれば返せますけどね。 Perl http://www.prenavi.net/~myoujin/tech/perl.html の「ガベージコレクション」のあたりを参照してください。

gle_gle
質問者

お礼

問題ないということがよく分かりました。ありがとうございました。

その他の回答 (1)

  • s_saike
  • ベストアンサー率46% (36/77)
回答No.1

perlの場合、変数をサブルーチン内でのみ有効にするには、local()を使用する必要があります。それ以外は全てグローバル変数となります。

gle_gle
質問者

お礼

参考になりました。ありがとうございました。

関連するQ&A

  • サブルーチンの戻り値

    すみません、教えてください。 サブルーチンの戻り値に、複数の配列を指定したいと思っています。 return(@data1,@data2,@data3,@data4); これら配列を戻り値として渡す時、4つの配列として渡す場合 サブルーチンを呼ぶ時はどのように記述すればよいでしょうか? それぞれ、配列のデータ量が違ったりしています。 やはり一度、一つの配列としてそれを区分していくやり方しかないですかね? よろしくお願いします。

    • ベストアンサー
    • Perl
  • Perlは戻り値で、ハッシュや配列を正しく返さないのでしょうか?

    Perlは戻り値で、ハッシュや配列を正しく返さないのでしょうか? 返せるように見えて実際は、歯抜けのデータなど、不安定で使い物になりません。 よって、リファレンスでスカラー値で利用するのが正論でしょうか? $a = ''; %b = (); @c = (); ○ return ($a, \$b, \$c); × retuen ($a, %b, @c); ○ my ($a, $b, $c) = aru_kansuu($hikkey, ('komori')); × my ($a, %b, @c) = aru_kansuu($hikkey, ('komori'));

    • ベストアンサー
    • Perl
  • ハッシュのリファレンスを戻り値にしたい

    PHPでハッシュのリファレンスを戻り値にする方法が知りたいです。 perlでは return \%hash; ですが、phpではどうなるのでしょうか? 他に別の方法があるのでしたらそれでも構いません。

    • ベストアンサー
    • PHP
  • サブルーチンへ渡した配列のリファレンスをデリファレンスするのが面倒なのですが。。

    MAIN: {   my @array = (1 .. 5);   print three(\@array);   exit; } sub three {   my $array = shift;   return $$array[2]; } のように、サブルーチンに配列リファレンスを渡したあと、$$array[2]のようにデリファレンスするのが面倒なのですが、 このとき$array[2]と書ける何か良い方法はないでしょうか? # 大きな配列を取り扱うので、リファレンスを使いたいんです。。 型グロブを使うことも考えたのですが、サブルーチン内でmyで宣言出来なくて、スコープ的にまずくなりそうなので断念しました; どなたかアドバイスしていただけると嬉しいです。。

    • ベストアンサー
    • Perl
  • Perlです。サブルーチンについて

    以下の文はあっていますでしょうか。 # サブルーチンを呼び出して引数は 3 とする。 # そして返ってきた戻り値を変数$aに代入せよ。 $a=&a(3); # サブルーチン名aせよ。 sub a{ # $_[0]が引数 3 となりプラス1して変数$bに代入せよ。 $b=$_[0]+1; # 変数$bの内容を戻り値として返せ。 return $b; } # 変数$aの内容を表示せよ。 print "$a";

    • ベストアンサー
    • Perl
  • 【Perl】サブルーチンから多次元配列を戻したい

    【Perl】サブルーチンから多次元配列を戻したい サブルーチン内で作った2次元配列と1つの変数(例:@listと$i)をリターンしたいのですが、どのようにすれば良いでしょうか? ↓サブルーチン(calc) return (@list, $i); ↓メイン my $a = 12; my (@list, $i) = &calc($a); 間違っていると思いますが、現時点でのプログラムを一部書きました。 ご回答よろしくお願いします!

    • ベストアンサー
    • Perl
  • ハッシュリファレンスの未定義

    サブルーチン/ハッシュリ/ファレンスで悩んでいます。 my (@r); $r[1]{"A"} = "1-A"; # 代入 &s(\@r); print $r[1]{"A"},"\n"; # 参照 print $r[2]{"B"},"\n"; # 参照 サブルーチン側でできない。 # sub s() { my ($c)=@_; @$c[1]->{"A"} = "1111-AAAA"; # もちろん代入できる @$c[2]->{"B"} = "2-B"; # 代入 これができない(ハッシュリファレンスの未定義エラー) } サブルーチン側で新規ハッシュのところに代入ができないのですが どのようにすればいいのでしょうか。

    • ベストアンサー
    • Perl
  • ハッシュのリファレンスを用いた処理

    ActivePerl 5.8 , WinXP SP2の環境です。 Perl スクリプトを用い、ファイルから複数のブロックからなる情報をよみとり、個別のハッシュを作り、それをリファレンスの配列としてまとめて後から参照するという操作をしたいのですが、詰まってしまいました。。 例として読み取るファイルは ---input.txt--------- >1 Jan 1 Feb 4 >2 Mar 9 Apr 3 >3 Oct 8 Nov 4 ------------------ ここから1,2,3の個別のハッシュ {Jan => 1 Feb => 4} {Mar=> 9 Apr =>3} {Oct =>8 Nov =>4} を作成し、それぞれのハッシュのリファレンスの配列をつくり、その後からすべてのハッシュの中身を個別に出力させたいと思いました。 次のようなスクリプトを作成したのですが思ったように作動しません。 use strict; open (IN, "input.txt") or die ("cant open file \n"); my $reff; my @array_of_reff; my %hash; my $count = 0; while(<IN>){ my $line = $_; ######ここでは各ブロックの頭の ">"を認識し、2個目以降であれば直前までで作ったハッシュのリファレンス($reff)を配列@array_of_reffに入れる。 if($line =~ /^>/){ if($count >0){ $reff = \%hash ; push (@array_of_reff, $reff); %hash = (); } $count++; } ########ここではアルファベットが入った行を認識して、ハッシュに追加しています if($line =~ /^[A-Za-z]/){           $line =~ /([A-Za-z]+)\s+/; my $month = $1; $line =~ /\s+(\d+)/; my $day= $1; $hash{$month} = $day;     } ###ここはファイルの最後になったら直前まで作っていたハッシュののリファレンス($reff)を配列@array_of_reffに入れる。 if( eof ){ $reff = \%hash ; push (@array_of_reff, $reff); } } #####ハッシュのリファレンスの配列(@array_of_reff)からもとのハッシュを参照し、ハッシュごとに出力 foreach my $reff_of_hash (@array_of_reff){    print "output";    while( (my $key,my $value) = each %$reff_of_hash ){     print "\n" , $key, " : ", $value, ;    } } このスクリプトを実行すると Nov 4 Oct 8 という3つめのハッシュのなかみが3回出力されてしまいます。自分では3つの別のハッシュをつくっているつもりでも、どうやら1種類しか作れていない、もしくはハッシュが上書きされているようなのですが、原因がわかりません。 この例だけ見るとハッシュのリファレンスを使う必要はないのですが、実際にはもうすこし大きいスクリプトで"ハッシュのリファレンスの配列を他のサブルーチンに渡す"ということを想定しており、これが解決できず先に進めない状態です。 アドバイス、解決法がわかったら教えていただけないでしょうか。

    • ベストアンサー
    • Perl
  • Perlの戻り値について

    配列の戻り値が理解できていないのですが、 Perlで正しく動作させるためには どのように記述したら良いのでしょうか? 戻り値の動作を詳しく書いてある(出来れば図入りで) 本はありますか? 例) sub a { my @a = ('A'); return (@a, "B", 2); } my (@a, $b, $c) = &a; print "a=[@a] b=[$b] c=[$c]\n"; # a=[A] b=[B] c=[2] # これを期待していたが # a=[A B 2] b=[] c=[] # こちらになる

    • ベストアンサー
    • Perl
  • 隔絶されているサブルーチン間の通信の方法

    以下のようなFortranのサブルーチンとモジュールがあります。これを見ると、サブルーチンA,Bはモジュールa,bが別なのでデータ的に隔絶されていることになります。もし、このような場合、サブルーチンA,Bの間で何らかの変数を共有するようなことをしたい場合、どのような方法があるでしょうか。サブルーチンの引数を使うのは混乱の原因になりそうなので、できればmoduleの方で処理できないかと思うのですが。 混乱しそうなところなので、やり方をいろいろ比較して見てみたいと思います。Cではグローバル変数のように全体で共有する変数を用意するのかなと思いますが。 module a end module module b end module subroutine A use a end subroutin B use b end Fortranについてはここでは特設会議室はありませんが、どこかいいところがあるでしょうか。Cの専門家はいろんなことに通じていると思うのでここにお尋ねしました。よろしくお願いします。

専門家に質問してみよう