ページ 11

関数が仕事していない?

Posted: 2009年8月19日(水) 19:53
by uwlover
このような簡単なソースコードなのですが、
#include <iostream>
using namespace std;

void func(int x);

int main()
{
	int p = 1234;

	cout << p << endl;

	func(p);

	cout << p << endl;

	return 0;
}
void func(int x)
{
	x *= 2;
}
関数プロトタイプ宣言の練習を兼ねてわざと関数にint型変数pの値を2倍にするようにした(このぐらいなら
関数に2倍処理してもらう必要ないですからね、普通は)のですが、これで実際にやってみると出力はどっちの出力も1234になってしまいます。つまり、関数で2倍にされておらず、初期化したときのpの値がそのまま出力されていることになります。
しかし、次のようにポインタを使うと、
#include <iostream>
using namespace std;

void func(int *x);

int main()
{
	int p = 1234;

	cout << p << endl;

	func(&p);

	cout << p << endl;

	return 0;
}
void func(int *x)
{
	*x *= 2;
}
こうすると最初の出力は1234に、最後の出力は2468になっています。つまりちゃんと関数が仕事して
います。どうしてこのような違いが生じるのでしょうか?代入の詳しい仕組みに代入は実はコピーである云々と
いう話をどこかで聞いたことがある気がするのですが、その辺が関係しているのかなぁと推察していますが、
やっぱり全然分かりません。

Re:関数が仕事していない?

Posted: 2009年8月19日(水) 19:57
by non
値渡しと参照渡しで検索すると、たくさん説明が出ますので、それを読んで
わからないことを質問してください。

Re:関数が仕事していない?

Posted: 2009年8月19日(水) 20:05
by dic
ポインタ関連の質問ですね
最初の方法 void func( int x ) 関数が呼ばれると
void func( int x ) の x には呼び出し時の引数1234がコピーされます
そしてこのコピーは関数void func( int x ) 内のみで有効となります
関数 void func( int x ) を抜けるとこの値は無効になります
具体的に言うと int main() の int p の値だけが void func( int x ) の int x にコピーされます


2番目の方法 void func( int *x ) 関数は
int main() 関数の int p のアドレス値が引数として渡されます
そのアドレスは int *x に代入されます
そして、そのアドレスの内容を2倍しています
なので、関数 void func( int *x ) を抜けてもint main() の int p を変更しているので
2468となります


2番目の方法のやり方を理解しているので分かるかなとは思いますがいかがでしょう?

Re:関数が仕事していない?

Posted: 2009年8月19日(水) 20:16
by owata
func関数の返り値がないだけなのでは?

Re:関数が仕事していない?

Posted: 2009年8月19日(水) 20:24
by uwlover
どうもありがとうございます、その方面で検索してみました。
先の例で言うと、func(p)の場合は値渡しと言い、funcに渡されるのはpの値のコピーであり、funcで処理
される値はそのコピーされた値だから元の値自体が処理されるわけではない。他方、func(&p)の場合は参照
渡しと言い、funcに渡されるのはpのアドレスだからfuncはアドレスからpの値を取り出すことによってpの
値そのものを処理できる。だからpの値を変更することが出来る。以上のような感じになるんでしょうか?

しかし、そうなると疑問が生じます。コピーのpを処理していた関数の場合、その処理されたpはどういう状態に
なっているんでしょうか?もしかして、放置されたまま結局使われることなくプログラムが終了した、という
ことになるんでしょうか?

Re:関数が仕事していない?

Posted: 2009年8月19日(水) 20:32
by uwlover
って、書き込んでいる内にdicさんが疑問の答えにあたる内容を提供してくださっているようですね。
コピーのpはfunc内部でのみ有効な変数だから、値渡しで2468を実現したいのならfunc内で出力すれば
よいってことになりますね。(実行しましたが成功しました)
今回は渡しの仕組みと変数の寿命(?)について勉強になりました。コピーのpはコピー先の関数内でない、
というのも大きなポイントだったように思います。皆さんどうもありがとうございました。

Re:関数が仕事していない?

Posted: 2009年8月19日(水) 20:33
by non
>コピーのpを処理していた関数の場合、その処理されたpはどういう状態に
なっているんでしょうか?

関数が終わったときに、変数は解放されます。したがって、returnなどで返さない限りは
呼び出した側では使えません。

Re:関数が仕事していない?

Posted: 2009年8月19日(水) 20:35
by uwlover
>コピーのpはコピー先の関数内でない、

一体何を言ってるんだか…コピーのpはコピー先の関数内でしか有効でない、ということです。