Locked History Actions

ROOT/Programing

ROOT/Programing (書きかけ)

ヒストグラムを関数から戻す

  • ヒストグラム (TH1D クラスのインスタンス) のポインタを関数から戻す場合、ポインタのポインタを使うか、ポインタの参照を使う。まず、C++ の文法を思い出す。
  • 関数から値を戻す

  • 以下のコードを実行しても 200 とは表示されない。func 関数内の int i は main() 内の int j とは別物であり、func で i を変更しても、main 関数内の j には影響しない。関数の引数は、呼び出し元から関数に値を渡すものであり、関数から値を戻すものではない。すなわち、基本的に関数の引数は一方通行のものである。
  • #include <iostream>
    
    void func(int j){
      std::cout << j << std::endl; // 100 と表示される
      j = 200;
      return;
    }
    
    void main(){
      int i = 100;
      func(i);
      std::cout << i << std::endl; // 100 と表示され、func 内の変更は反映されない
      return;
    }
  • 上記のコードを実行すると main 関数内の int i のメモリ領域と func 関数内の int j のメモリ領域が確保される。func が呼び出されるところで main 関数内の int i のメモリ領域にある 100 という値が func 関数内の int j に代入される。func 関数内でこの値を表示することが可能であるが、func 関数内の int j に値を代入しても、 main 関数内の int i には影響しない。
  • 関数内で値を変更し、その値を呼び出し元に戻したい場合は、ポインタを関数に渡すか、参照を使う。これで、あたかも関数から値を戻しているような動作を実現できる。
  • ポインタを渡す

    • #include <iostream>
      
      void func(int* j){
        std::cout << *j << std::endl; // 100 と表示される
        *j = 200;
        return;
      }
      
      void main(){
        int i = 100;
        func(&i);
        std::cout << i << std::endl; // 200 とは表示される
        return;
      }
    • 上記のコードを実行すると main 関数内の int i のメモリ領域が確保されるが、func 関数内の int j はポインタ変数 j のメモリ領域と j に格納される値(アドレス)が指し示す int 型のメモリ領域が確保される(だぶん)。func 関数が呼び出されると、 main 関数内の int i のアドレスが func 関数内のポインタ変数 i に代入される。このポインタ変数が指し示すメモリ領域は、main 内の int i が確保したメモリ領域なので、func 内でこの領域に値を書き込むことは、呼び出し元の int i に値を書き込むことと同値である。すなわち、呼び出し元の変数の値を変更していることになるので、関数が値を戻しているような動作を実現していることになる。
  • 参照を渡す

    • #include <iostream>
      
      void func(int& i){
        std::cout << i << std::endl; // 100 と表示される
        i = 200;
      
        return;
      }
      
      void main(){
        int i = 100;
        func(i);
        std::cout << i << std::endl; // 200 とは表示される
        return;
      }
    • 上記のコードを実行すると main 関数内の int i のメモリ領域は確保されるが func 関数の int& j は参照型なので、この型に対するメモリは確保されない。func が呼び出されると int& j = i という操作が行われ func 関数内で i の参照 j を扱うことが可能となる。参照 j は i の別名であり、i と j はメモリを共有 (?) しており、i と j のアドレスは等しい。すなわち j に対する操作は i に対する操作となる。func 関数内で j に値を書き込めば、呼び出し元の i に値を書き込むことと同値である。呼び出し元の変数の値を変更しているので、関数が値を戻しているような動作を実現していることになる。