• 締切済み

使わなくなった変数に違う値を入れるのはマズイ?

CやJAVAのような、厳密な型の存在しない言語(Perl、PHP、Javascriptなど)についての質問です。 プログラミングをしていて、途中である変数が要らなくなることがあります。これを、せっかく宣言したので別の値、それも型が違ったりプリミティブ型の値を入れてたのにオブジェクト型を入れるとか、そういう使い方をすることがあります。 例(Javascriptの場合) $hen = new Array(10); $hen[0] = 0; $hen[1] = 1; . . . for (i=0; i<10; i++) { print $hen[$i]; } //ここで配列henは要らなくなった。変わりに文字列が欲しい。 $hen = "String"; //せっかく変数henがあるので、これを入れ物として使う。 最近、C++の勉強をして、このようなケースで変数名との結びつきが無くなった変数の中身は、存在はするがアクセスする手段を失った「ゴミ」となるということを知りました。多くの言語も、同じような構造だとも知りましたが、同時に「ガベージコレクション」を装備している言語は、プログラムがその値が以降使われないと判断された場合は自動でその変数に割り当てているメモリを開放して処理速度向上を図る・・・とありました。では、例として挙げたケースでは、ガベージコレクションを装備していれば、ゴミは発生するがプログラムが自動でメモリを開放してくれるのでそこまで気にしなくても良い、という解釈で良いのでしょうか?私はPHPが得意なのですが、PHPは標準ではガベージコレクションを装備していないようなので、気をつけてプログラミングしようと思っているのですが。 余談ですが、「変数名と内容が一致しなくなるケースがある($arr = new Array();を後で$arr = "String";とするなど)からやめたほうが良い」という突っ込みはナシでお願いします。その点は承知していますので。

みんなの回答

  • notnot
  • ベストアンサー率47% (4846/10257)
回答No.3

他の方も書かれてますが、良くないスタイルです。 名前一般に関しては、 ・同じ物は同じ名前で呼ぶ ・違う物には違う名前を付ける を原則だと思ってください。 #2の方の書かれた >プログラミングの基本の基本に「自動ガベージコレクションは、極力、発生させてはならない」と言うのがあります。 は、言語によってガベージコレクションの考え方が違うので、一般論ではありません。多くの動的言語では、メモリ管理をガベージコレクタに任せます。 >なぜなら「自動ガベージコレクション中は、本来のプログラムの動作が停止し、数秒~十数秒の間、まるでフリーズしたかのようになる」からです。 ガベージコレクタにメモリ管理を任せるのが普通では無い言語で、ガベージコレクションを発生させるとこういう状態になるかもしれません。

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.2

まず第1に「要らないと思って変数を使い回しした後で、コードを変更する必要が出て、使い回しした後で元の変数の値が必要になっちゃった」って時に、すごく大変な思いをするでしょう。 変更作業には、本来行う必要のない「使い回しをしないように修正する作業」が伴います。もし使い回しをしていなければ「一切、する必要の無い作業」です。 その変更を行う前に「ここで値を参照しているのは、元の値を参照しているのか、使い回しした後の値を参照しているのか、どっちなのか覚えてない」って場合には「使い回しをしないように修正する作業」そのものが出来ません。 >最近、C++の勉強をして、このようなケースで変数名との結びつきが無くなった変数の中身は、存在はするがアクセスする手段を失った「ゴミ」となるということを知りました。 何か「大きな勘違い」をしていますね。 CやC++の場合の「存在はするがアクセスする手段を失ったゴミ」とは、例えば「newで宣言して確保はしたがdeleteで削除を行わないまま関数を抜けて参照スコープを失った変数」や「mallocで確保はしたがfreeしてないメモリ」などを言います。 これは、普通は「メモリリーク」と呼び「重大なバグ」に分類されます。 なぜなら「そういうプログラムが長く動き続けると、システムのメモリリソースを食い尽くして、システムそのものを停止させる事態」にまで発展するからです。 >自動でその変数に割り当てているメモリを開放して処理速度向上を図る・・・とありました。 プログラミングの基本の基本に「自動ガベージコレクションは、極力、発生させてはならない」と言うのがあります。 なぜなら「自動ガベージコレクション中は、本来のプログラムの動作が停止し、数秒~十数秒の間、まるでフリーズしたかのようになる」からです。 ブラウザで「送信」のボタンを押した瞬間、ガベージが起きて20秒以上も「画面が切り替わらず、反応がない」としたら、ユーザーはどういう行動に出るでしょうか?間違い無く言えるのは「黙ってじっと待ってる人は100人に1人居るか居ないか」でしょう。 >ガベージコレクションを装備していれば、ゴミは発生するがプログラムが自動でメモリを開放してくれるのでそこまで気にしなくても良い、という解釈で良いのでしょうか? ダメです。 ガベージコレクションを装備していようがいまいが、リークしたメモリは「システムを再起動するか、シャットダウンしない限り、メモリリソースを食い続ける」ので。 そういう解釈で居る限り「マトモなプログラマとして絶対に認めてもらえない」ので、もし将来プログラミングで食って行くつもりなら、考え方を改める必要があるでしょう。 てゆ~か「変数の使い回し」が許されるのは「組み込み用ファームウェアで、使えるRAMメモリが4キロバイトしかない」とかってプラットフォームでコードを書く時だけです。 現在主流の「WindowsPC」がプラットフォームの場合は「有り余るメモリを湯水のように使っても全然問題無い」ので「使い回しする必要が無い」です。

回答No.1

変数の使い回しはやめた方がよいです。 コードを読む上で,「今何に関する情報が入っているのか」という情報が変更されてしまう上,将来コード変更する場合に大きな問題点になり得ます。 たとえば将来コードの変更を行い,"String"の代入後に配列の$henが必要になることがあった場合,どちらかの変数名を変更したり,配列の$henを別の変数に移したりしなければならなくなります。 古いCのようにループ変数をスコープに閉じこめることができない環境におけるループ変数iや,一部の組み込み環境のようにRAMの仕様を極限まで切り詰めなければならない場合を除けば,変数を使い回すことのメリットはなく,デメリットだけが存在すると考えて間違いないです。

関連するQ&A

  • array()の中に変数の値(テキスト)を入れたい

    いつもお世話になっております。 PHP5.3で、 $number = '1,2,3,4'; という文字列の値が入った変数があり、この変数を"array()"の()の中に呼び出したいのですが定義の仕方が分かりません。 イメージとしてはarray($number)のような感じで、array(1,2,3,4)という配列を定義したいです。 (勿論↑では動きませんでした;) ご教授宜しくお願い致します。

    • ベストアンサー
    • PHP
  • 変数を動的に利用するには?

    Javaプログラミングの質問です。 下記のように変数を定義しておき、 String aaa_0 = "AAA1"; String aaa_1 = "AAA2"; 例えば、これらの変数の値を次のようにして使えますでしょうか? (できませんが、やりたいことは、なんとなく伝わったかと思います。) for(int i=0;i<2;i++){ System.out.println("aaa_" + i); } 変数を動的に呼び出せますでしょうか? アドバイスお願い致します。

  • phpで左辺が変数でイコールを挟んで右辺に入る値を

    phpで左辺が変数でイコールを挟んで右辺に入る値を型と呼びますよね? integer string float bool 等 この画像にある $message = $job.$count.”名募集”; の場合等を何型と呼ぶんでしょうか?

    • ベストアンサー
    • PHP
  • REQUEST_URIなどの環境変数の値を見たい

    REQUEST_URIやQUERY_STRINGなどの環境変数の値を直接確認したいです。 しかしphpなどの言語でなくlinuxの命令やapacheのディレクティブで出力するなどで知る方法はないでしょうか。 またphpでREQUEST_URIなどを確認した場合それはapacheのディレクティブ処理時の値と同じという保証はあるのでしょうか。 もう一つ、apacheをローカルで動作させている場合REQUEST_URI中でQUERY_STRINGに相当する部分が無いということはありうるでしょうか。 どれか一つでも助言頂けると助かります。

  • PHP4で、メンバ変数の値を忘れてしまう2

    PHP4での質問です。 前の質問がわかりにくかったので、書き直しました。 オブジェクト指向的にいかがなものかとは思いますが、オブジェクトのメンバ変数を直接外部から変更したいと思います。 ---------<a.php>---------- class myClass {   var member = 0; } ---------<b.php>---------- $ary_c = array(); for ($i=0; $i<10; $i++) {   $c = new myClass();   $c->member = 1;   echo "(1)c->member=".$c->member;   array_push($ary_c, $c); } foreach ($ary_c as $c) {   echo "(2)c->member=".$c->member; } ------------------------------ 以上の様なソースで、(1)のデバッグライトでは、メンバ変数memberの値は1であるのに、(2)のデバッグライトでは、0になってしまいます。 この原因がお分かりのかた、もしよろしければ知恵をお貸し下さい。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • phpから値をとってきて変数に格納するには?

    phpから値をとってきて変数に格納するにはどうすればいいのでしょう? ちなみにjavascriptはほとんどさわったことのない初心者です。 やりたいことを具体的に説明します。 p.php 「 <?php yy = "test string"; //?(1) ?> 」 js.html 「 <script language="javascript"> var xx; //?(2) </script> 」 最終的に、php内の変数「yy」の内容をjavascriptの変数「xx」にいれたいのです。 よろしくお願いします。

  • phpでハイパーリンクして値を持っていきたい

    今phpを使ってhtmlのタグを使いハイパーリンクして値を持っていきたいのですけどよくわかりません for($i;$i>=0;$i--){ echo '<a href="user.php">'.$arr[$i].'</a><br />'; echo $i; このようにプログラムは書いてます user.phpに arr[$i]の値をそれぞれ持っていきたいのですけど どのように書けばいいでしょうか?

    • ベストアンサー
    • PHP
  • 参照変数の親配列を取得

    データの多次元配列があって、値に応じて動的に関数を選択し 中身の値を引数で渡すみたいな感じの処理をしています ほとんどの処理は中身の値だけあれば事足りるのですが 稀にキー値を使いたい処理がでてきます 本当に稀なので引数にキー値も渡すようにするのは 無駄が多くなるように思うので避けたく できれば参照変数で渡される値から 親配列でのキー値を取得したいと思っています $arr2A=array('a'=>array('fnc'=>'A','あ','い','う'),'b'=>array('fnc'=>'B','か','き','く'),'c'=>array('fnc'=>'C','さ','し','す')); $arr2B=array('a'=>array('fnc'=>'A','あ','い','う'),'b'=>array('fnc'=>'B','か','き','く'),'c'=>array('fnc'=>'C','さ','し','す')); $arr2C=array('a'=>array('fnc'=>'A','あ','い','う'),'b'=>array('fnc'=>'B','か','き','く'),'c'=>array('fnc'=>'C','さ','し','す')); foreach($arr2A as $key=>$val){ $fncs[$val['fnc']]($val); } foreach($arr2B as $key=>$val){ $fncs[$val['fnc']]($val); } foreach($arr2C as $key=>$val){ $fncs[$val['fnc']]($val); } $fncs=array( A=>function(&$arr){ }, B=>function(&$arr){ }, C=>function(&$arr){ //ここで稀にキー値も使いたい }); 実際のコードはかなり長いので載せられませんが 要約すると上記のような感じの処理です まずどのデータ配列の集合から渡されたのかが明確ではありませんので indexOfなどでキー値を得るのというのが難しいです 現在は、その処理が必要なデータ行について処理前に 中身にキー値をあらかじめ入れてしまう というように対応しているので、一応解決はしているのですが もし参照変数から親配列を得る方法が あればと思い質問させていただきました ”そんなものはない”という回答も あきらめつくのでお願いします

    • ベストアンサー
    • PHP
  • 配列の次元を超えてランダムに選択したい

    PHP5.2.4を使用しています。 例えば、次のような2次元以上の配列があったときに $arr[0][0] = array('a' => 1, 'b' => 11); $arr[0][1] = array('a' => 2, 'b' => 5); $arr[0][2] = array('a' => 3, 'b' => 20); $arr[1][0] = array('a' => 4, 'b' => 3); $arr[1][1] = array('a' => 5, 'b' => 30); この5つから、'b'の値が10以上の候補だけのインデックス($arr【[1][1]】←この部分)を ランダムに1つ選ぶ方法はどのようになるのでしょうか? 自分が考えたのは for ($i = 0; $i < count($arr); $i++) {  for ($j = 0; $j < count($arr[$i]); $j++)  {   if ($arr[$i][$j]['b'] < 10)    continue;   $new_arr[] = array('index2' => $i, 'index1' => $j);  } } $key = array_rand($new_arr, 1); print_r($new_arr[$key]); //Array ( [index2] => 0 [index1] => 0 ) //Array ( [index2] => 0 [index1] => 2 ) //Array ( [index2] => 1 [index1] => 1 ) //いずれかが選択される なんですが、これだとあまり良いやり方だと思わなくて なにか別のやり方はあるのでしょうか?

    • 締切済み
    • PHP
  • 変数の継承について

    初めまして。最近、独習Javaで勉強を始めた者です。ゆっくりながら継承の所まで進みました。 abstract class Monster{ String monster; } class Vampire extends Monster{ String monster = "Vampire"; } class Zombie extends Monster{ String monster = "Zombie"; } class NewSougou3{ public static void main(String args[]){ Vampire vam = new Vampire(); Zombie zom = new Zombie(); Monster array[] = new Monster[2]; array[0] = vam; array[1] = zom; for (int i = 0 ; i < 2 ; i++){ System.out.println(array[1].monster); } } } というプログラムを作ったのですが、実行すると"null"が二つ出てきただけで正しい"Vampire"と"Zombie"が表示されません。Monsterクラスで定義したmonsterの値(既定)が表示されていると思うのですが、Monster型で宣言した配列にVampire、Zombieクラスをインスタンス化して代入してもそれは反映されないのでしょうか?スーパークラスであるMonsterクラスで変数monsterを宣言し、二つのクラスをインスタンス化した時に変数monsterにそれぞれの値が代入されると思ったのですが… なにぶん始めたばかりなので見当違いのことを質問しているかもしれません。その辺はお許し下さい。よろしくお願いします。

    • ベストアンサー
    • Java

専門家に質問してみよう