Comments
Description
Transcript
ポインタと参照渡し
1 ポインタと参照渡し ポインタ ポインタとは、アドレスを代入するための変数 (型) である。 ある型のアドレスを代入できるポインタは型* 変数名で宣言する。 int a のアドレスを代入できるポインタは、int* a イメージ的には xµ = (x1 , x2 , · · · xn ) の x が値を代入する普通の変数で、 µはアドレスを代入するポインタ アドレス呼び出し方 ポインタにアドレスを代入するときに適当にアドレスを自分で代入しても、あまり意味が無い (そのアドレスに のっている値がわからないから)。なので任意の変数 x のアドレスを呼び出す方法を示す。 • 変数に&を付けるとアドレスの値になる。 • 配列や関数の場合はその名前を書けばアドレスの値になる。 例 x=10 という x のアドレスの値は&x で表される。 student[100] や function(x,y) のアドレスの値は student function で表される。 実際に代入する場合は int* a=&x これでポインタ a には x のアドレスが代入された。 余談 ちなみに配列のアドレスは先頭のアドレスが採用される。 &(student[0])=student は等価である。 逆にポインタから実際の値の呼び出し方 *ポインタ とするとメモリにのっている実際の値が出てくる。← この*はポインタ変数の宣言の*とは書き方は同 じだが意味が全然違うので注意!! 例 int x=10 int* a=&x *a の値は 10 となる。 *a=100 を代入すると x は 100 が代入されたことになる。 参照渡し (例外な文法) 関数の引数として取れるものは 2 種類ある。(実際の値が入ってる変数を引数) 値渡しと、(アドレスの値を引数) 参 照渡しだ。 2 int& x という特別な参照と呼ばれる変数を使う。 int& x は宣言の時以外は int x と全く同じに扱える。 例 int x function(x)← 値渡し function(&x)← 参照渡し なぜ参照渡しが必要なのか? 関数の中の変数はローカルであるので、関数を抜けた時点で消えてしまう。 なので関数のなかで引数としてもってきた変数をいじっても、関数を超えて変数を操作することが普通はできない。 参照渡しをつかうと関数を超えて変数を操作することができる。 具体例は Refere.cpp に示す。 #include <iostream> using namespace std; void Change(int& x){ //ここを x か &x かで結果が変わる。 &x の参照渡しにしないと値が変更されない。 x=100; } int main(){ int x=20; Change(x); cout << "変更後の値"<<x<<endl;} ポインタと参照渡しの違い 具体例を見たほうがはやい ポインタでも参照渡しと同じ機能をもつプログラムを書くことが可能。 参照を使ったプログラム Refere.cpp を全く同じ機能のポインタを使ったプログラム Pointa.cpp で書きなおす。 具体例 Pointa.cpp #include <iostream> using namespace std; void Change(int* x){ *x=*x+100; } int main(){ int x=20; Change(&x); cout << "変更後の値"<<x<<endl; } ポインタはローカルな変数 (コピー) の値を変えるんじゃなくて、ポインタの値 (アドレス) が指す実際の変数 (原 本) の値を変えるということを行っている。 ポインタ 参照渡し メリット 参照先を途中で変更することができる 参照先は固定 (宣言の時はどの変数を指すかを決めな デメリット 実際の値を出すときにいちいち*を付けないといけない。 宣言のときに&さえ付けていれば、後は普通の変数 特徴 あくまで変数。万能だがちょっと危険な操作も可能 あくまで定数 (アドレス)。ポインタのエイリアスの性 コメント:バグを減らす意味でも、ポインタを使うか参照渡しを使うかは統一したほうがいい。ローカル変数の受け 渡しを行うだけなら参照渡しを積極的に使うべき。 ただローカルな配列を受け渡すときは、ポインタを使っているので意識していると混乱しにくいと思う。