値と参照とポインタ
値渡しは兎も角、参照とポインタを使い分ける場合がわからん。いろんな所から斧が飛んできそうだが、どちらも変数のアドレスを扱っているなぁ程度の理解。この理解でいいのかな。
void swap(int& x, int& y){ int temp; temp=x; x=y; y=temp; }
これは参照。呼び出し元はswap(x,y)
って書く。
void swap(int *x, int *y){ int temp; temp=*x; *x=*y; *y=temp; }
こっちがポインタ。呼び出し元はswap(&x,&y)
みたいな書き方をする。
関数に渡す実引数が複数ある場合、そのうちのいくつかだけを関数に渡す際に、参照だと呼び出し元見ただけじゃ「あれ?どの変数を渡した?」ってなるけど、ポインタだったら&
を付けるからどの変数(のアドレス)を関数に渡したのかわかるよねって話らしい。なるほどな~。
でポインタや参照を扱ったコードの理解のために、呼び出し元や関数の仮引数部に*や&を付けたり付けなかったりして遊んでみたわけだけど、ポインタの呼び出し元をswap(x,y)
ってしても動いた。んんんんんんん?????
#include <iostream> using namespace std; void swap(int *x, int *y){ int temp; temp=*x; *x=*y; *y=temp; } int main(){ int num1 =5,num2=10; cout <<"num1:" << num1 << "\n"; cout <<"num2:" << num2 << "\n"; cout <<"交換\n"; swap(num1,num2); cout <<"num1:" << num1 << "\n"; cout <<"num2:" << num2 << "\n"; return 0; }
なんで動くんですか....。全然わからん。 取りあえず別に簡単なコードを書いてみた。
#include <iostream> using namespace std; void add(int* x,int* y); int main() { int sub1=0,sub2=0; cout << "2科目分の点数を入力:\n"; cin >> sub1 >> sub2; add(sub1,sub2); cout << "12点加算した\n"; cout <<"sub1:" << sub1 <<'\n'; cout <<"sub2:" << sub2 <<'\n'; return 0; } void add(int* x,int* y){ int a=12; *x += a; *y += a; }
add(&sub1,&sub2)にしないとダメみたい。だからこのコードは動かない。当然だよなぁ!?
不思議に思ってswap関数の方のソースコードをadd関数の方に書き換えると何故かswap関数の挙動をする。これは完全に私が馬鹿でmain関数内のswap()を書き換え忘れてたというポカをやったという話(マヌケ)。でもお陰で気がつくことができた。
もしかしてと思い、C++ swapで検索するとstd::swapみたいなよくわかんないものがヒット。
#include <iostream> using namespace std; int main(){ int num1 =5,num2=10; cout <<"num1:" << num1 << "\n"; cout <<"num2:" << num2 << "\n"; cout <<"交換\n"; swap(num1,num2); cout <<"num1:" << num1 << "\n"; cout <<"num2:" << num2 << "\n"; return 0; }
動いた。num1とnum2が入れ替わってた。C++ってPythonみたいに関数があらかじめ定義されてるのかな?
ま、一つ目のポインタで書いたswap()関数は意味が無かった、動作してないってことは確認できた。C++の組み込み関数?の勉強もしなきゃここらの話は分からないということがわかった。先日、maxって関数名で関数を作ろうとしたけど謎のエラー吐いたのももしかすると同様の理由かもわからない。
ここのページの下の方にコードが張ってあってそれをみるとstd::swap(a,b)で入れ替わるからやはりそういうことだったのかと。ところでstd::coutとcoutの違いとその理由はなんだろうな?う~~~~~ん、勉強すればするだけ壁にぶつかるなぁ。
つまりポインタと参照は関数に飛ぶとき、呼び出し元の変数をその関数で更新してそれ以降もずっと適応させるために使うって理解している。関数に飛んで変数をいじるならポインタと参照を使えと。returnだと呼び出し元で別の変数に一度入れる必要があるけど、こっちならそんな必要も無いし複数の変数を同時に扱えるんじゃあないかな。
以下余談。
関数の中身でポインタを取り扱う時、例えばxに12を加算したいときに
x* += 12
って書くとprimary-expressionってエラー吐くんだが一体どういうことだー。アドレスに数字を入れるのって駄目なのかー?って悩みに悩みまくって
*x += 12
では?と気が付いて、たーのしー!ってなった。これに気がつくまでに1時間浪費した。たーのしー!