ぴよがち

技術的な話をします。みんなで強くなりましょう。

【C++】参照とポインター完全に理解した

色々試したのでメモ。

用意したもの

以下の 4 種類の関数を用意した。

  1. 値渡し(何もつけずに書いたやつ)

    #include <iostream>
    
    int sum(int in1, int in2) {
        return in1 + in2;
    }
    
    int main() {
        int input1, input2;
        std::cin >> input1 >> input2;
        int result = sum(input1, input2);
        std::cout << result << std::endl;
        return 0;
    }
    
  2. 参照渡し

    #include <iostream>
    
    int sum(int& in1, int& in2) {
        return in1 + in2;
    }
    
    int main() {
        int input1, input2;
        std::cin >> input1 >> input2;
        int result = sum(input1, input2);
        std::cout << result << std::endl;
        return 0;
    }
    
  3. ポインタ渡し(move)

    #include <iostream>
    #include <memory>
    
    int sum(std::unique_ptr<int> in1, std::unique_ptr<int> in2) {
        return *in1 + *in2;
    }
    
    int main() {
        std::unique_ptr<int> input1(new int (0)), input2(new int (0));
        std::cin >> *input1 >> *input2;
        int result = sum(std::move(input1), std::move(input2));
        std::cout << result << std::endl;
        return 0;
    }
    
  4. ポインタ参照渡し

    #include <iostream>
    #include <memory>
    
    int sum(std::unique_ptr<int>& in1, std::unique_ptr<int>& in2) {
        return *in1 + *in2;
    }
    
    int main() {
        std::unique_ptr<int> input1(new int (0)), input2(new int (0));
        std::cin >> *input1 >> *input2;
        int result = sum(input1, input2);
        std::cout << result << std::endl;
        return 0;
    }
    

それぞれの挙動

  1. 値渡し
    • コピーが渡る。
      • でかいデータをコピーすると時間がかかるので、用法に注意。
      • コピーなので、参照先で変数を変更・再代入しても当然参照元には影響しない。
    • 参照先を変更しても、参照元の変数には影響なし。
  2. 参照渡し
    • 参照が渡る
      • 参照先で読み書きができる。
    • 参照先で変更すると、参照元が変更される。
  3. ポインタ渡し(move)
    • ポインタが渡る
      • 参照先で読み書きができる。
    • 参照元の変数は、利用できなくなる。 (unspecified state になる。参考:std::move - cppreference.com
  4. ポインタ参照渡し
    • ポインタの参照が渡る
      • 参照先で読み書きができる。
    • 参照先で変更すると、参照元が変更される。

所感

C++なんもわからんので、ぼちぼち学んでいきたいところです。 Rustの方が怪しい書き方した時に警告出してくれがちなので現状すき。

おまけ

アセンブリで挙動追いかけてみた。 ほんとに上記の通りになってて面白い(当たり前)

アセンブリを表示したスクショ