参照・ポインタ

ポインタの参照渡しにちょっとひっかかったのでメモ。

関数に参照渡しとか

//仮引数が+100される
void function(int& x)
{
    x+=100;
}
//参照の初期化
int n[10];
int& r = n[3];

//初期化しかできなーい。
//参照先の変更はできなーい。

配列を関数に渡すときはポインタが使われる。

const

int n[5];
int m[5];
const int* p; //参照先は自由に変えられるが、*pの値は変更できない。初期化必須でない。
int* const q = n; //参照先を変更できないが、*qの値は変更可能。初期化必須。ていうか参照(&)と同じなのかな。

Init(p); //これはエラー。
Init(q); //ok

p = m; //ok
q = m: //エラー

constの直後が定数になる。

ポインタ渡しとポインタの参照渡し

void f(int* p)
{
	cout <<"(in f) p:" << (size_t)p << endl;
	cout <<"(in f) &p:" << (size_t)&p << endl;
}
void rf(int*& p)
{
	cout <<"(in rf) p:" << (size_t)p << endl;
	cout <<"(in rf) &p:" << (size_t)&p << endl;
}
int main() {
	int a = 10;
	int* p = &a;
	cout <<"(main) p:" << (size_t)p <<endl;
	cout <<"(main) &p:" << (size_t)&p <<endl;
	f(p);
	rf(p);
}

実行結果

(main) p:2665452
(main) &p:2665448
(in f) p:2665452
(in f) &p:2665328
(in rf) p:2665452
(in rf) &p:2665448

p:全て一致*1
&p:参照渡し(in rf)と(main)が一致*2

各ポインタの参照先は全て一致しているが、ポインタ呼び出しの場合はポインタ自身のアドレスが違ってたする。
ポインタ渡しだった場合、関数内でポインタの参照先を変更しても関数内のポインタとmain内のポインタは別物(アドレスが違う)ので反映されない。
参照渡しの場合、関数内でポインタはmainのポインタの参照(アドレスが同じ)なので、関数内で参照先を変更した場合はmainのポインタにも変更が反映される。

void change(int* p)
{
	static int a = 10;
	p = &a;
}
void rchange(int*& q)
{
	static int b = 10;
	q = &b;
}
int main()
{
int c = 5;
	int *pa = &c, *pb = &c;
	cout << "before change" << endl;
	cout << "*pa = "<< *pa << endl;
	cout << "*pb = "<< *pb << endl;
	change(pa);
	rchange(pb);
	cout << "after change" << endl;
	cout << "*pa = "<< *pa << endl;
	cout << "*pb = "<< *pb << endl;
}

実行結果

before change
*pa = 5
*pb = 5
after change
*pa = 5
*pb = 10

値渡しと参照渡しのポインタ版ってことですね。

*1:p: ポインタ変数pが格納してるアドレス

*2:&p: ポインタ変数p自身のアドレス