値渡しと参照渡しについての質問

このQ&Aのポイント
  • 関数内で仮引数xとyの値を交換する処理を行っていても、これは変数num1とnum2の値を「コピー」した5と10を交換しているにすぎません。
  • swap関数内で値を交換しても、呼び出し元の変数であるnum1とnum2に影響を与えることができません。
  • 値渡しとは関数に引数として渡す値がコピーされることを指し、参照渡しは変数のメモリ上のアドレスが渡されることを指します。
回答を見る
  • ベストアンサー

誤った関数に関する値渡しについて

こんにちは、まずはソースを記述します。 #include<iostream> using namespace std; //誤ったswap関数の宣言 void swap(int x, int y); int main() { int num1 = 5; int num2 = 10; cout << "変数num1の値は" << num1 << "です。\n"; cout << "変数num2の値は" << num2 << "です。\n"; cout << "変数num1とnum2の値を交換します。\n"; swap(num1, num2); cout << "変数num1の値は" << num1 << "です。\n"; cout << "変数num2の値は" << num2 << "です。\n"; return 0; } //誤ったswap関数の定義 void swap(int x, int y) { int tmp; tmp = x; x = y; y = tmp; } >>関数内で仮引数xとyの値を交換する処理を行っていても、これは変数num1とnum2の値を「コピー」した5と10を交換しているにすぎません。 swap関数内で値を交換しても、呼び出し元の変数であるnum1とnum2に影響を与えることができません。 ・・の文章の中から質問ですが値渡しとはどういうことでしょうか? 参照渡しとはどう違うのでしょうか? ご教示お願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • asciiz
  • ベストアンサー率70% (6642/9410)
回答No.3

>値渡しとはどういうことでしょうか? >参照渡しとはどう違うのでしょうか? 値渡しは、ご質問のソースどおりです。 >swap(num1, num2); 通常の関数呼び出しは皆こちらで、num1・num2の「値」を「コピー」して関数を呼び出し、結果(返り値)をどこにも保存していませんから、swap(入れ替え)したいのであれば用をなしません。 そこで、参照(メモリアドレス)渡しの出番です。 swap関数定義は次のように書き、 void swap(int *x_ptr, int *y_ptr) { int tmp; tmp = *x_ptr; *x_ptr = *y_ptr; *y_ptr = tmp; } 呼び出しもこう変えます。 swap(&num1, &num2); &num1 と書くと、num1変数の値が格納されているメモリアドレスを意味します。 メモリアドレスを渡してやることで(これが「参照渡し」)、swap関数内ではnum1変数の実態にアクセスし(*x_ptr)、書き換えることができます。 アドレスを格納する型をポインタと言い、x_ptr, y_ptr がそれに当たります。 気をつけなければいけないのは、ポインタはメモリアドレスしか示していないので、そこにどんな型の値が保存されているか、きっちりプログラマが管理しなければならないことです。 また、普段は変数名に隠蔽されているメモリアドレスを直接扱いますので、うっかり変数アドレスでない値を渡してしまうと、予想外のメモリ領域を破壊したりして、非常に厄介で見つけづらいバグを発生させてしまいます。(関数を呼ぶときに、&をつけ忘れるだけで容易に起こりうる) 正直、普段のプログラミングではほとんど使いませんが、グローバル変数を用意しなくても、渡した変数や構造体の中身を直接いじることができるという便利な書き方です。(でもうっかりバグを仕込んでしまうデメリットが大きくてですね…。)

aiueo6391
質問者

お礼

なるほどですね。 回答ありがとうございます。

その他の回答 (2)

回答No.2

swap(num1, num2); →  swap(&num1, &num2); void swap(int x, int y) { int tmp; tmp = x; x = y; y = tmp; } ↑をまるごと void swap(int *x, int *y) { int tmp; tmp = *x; *x = *y; *y = tmp; } 何が違うのかは、調べみればわかると思いますよ。

aiueo6391
質問者

お礼

回答ありがとうございます。

  • Wap58
  • ベストアンサー率33% (29/87)
回答No.1

値渡し:部下を信頼しない上司は重要な書類の元本を保存しコピーを部下に加工させます 参照渡し:部下を信頼してる上司は重要な書類の保管場所を部下に教え部下に加工させます

関連するQ&A

  • Cのポインタについて(関数への値渡し)

    C言語のポインタに関する質問です。関数に引数を渡す方法として以下の誤ったswap関数でなぜだめなのかいまいち得心できません。わかりやすくかみくだいて説明していただけると有り難いです。 できましたら、トレースともうしますか、変数の値の動きを詳細に段階的にプログラムの流れに沿って追っていって、だからこうなんだよ、みたいな解説がいただけたら有り難いです。わがままいってすみません。 /* 誤ったswap関数の宣言 */ void swap(int x, int y); int main(void) { int num1 = 5; int num2 = 10; printf("変数num1の値は%dです。¥n", num1); printf("変数num2の値は%dです。¥n", num2); printf("変数num1とnum2の値を交換します。¥n", num1); swap(num1, num2); printf("変数num1の値は%dです。¥n", num1); printf("変数num2の値は%dです。¥n", num2); return 0; } /* 誤ったswap関数の定義 */ void swap(int x, int y) { int tmp; tmp = x; x = y; y = tmp; } ---------- /* swap関数の宣言 */ void swap(int *pX, int *pY); int main(void) { int num1 = 5; int num2 = 10; printf("変数num1の値は%dです。¥n", num1); printf("変数num2の値は%dです。¥n", num2); printf("変数num1とnum2の値を交換します。¥n", num1); swap(&num1, &num2); printf("変数num1の値は%dです。¥n", num1); printf("変数num2の値は%dです。¥n", num2); return 0; } /* swap関数の定義 */ void swap(int *pX, int *pY) { int tmp; tmp = *pX; *pX = *pY; *pY = tmp; }

  • C++ 関数プロトタイプと値渡し・参照渡しについて

    次のコードは、入門書にあった値渡しのサンプルです。 値渡しなので、a=5 ,b=10が出力されます。 void swap(int x,int y); //←抜けていた int main(){ int a=5; int b=10; swap(a,b); cout<<"a="<< a << "\n"; cout<<"b="<<b<<"\n"; } void swap(int x,int y){ int tmp=x; x=y; y=tmp; } しかし、自分で入力したところ何故かa=10,b=5が出力されました。 (VisualC++2008で実行しました。) よく見てみると、上記1行目の関数プロトタイプが抜けていました。 入門書を読んだ限りでは、次の2点が理解できません。 (1)main関数の後ろにswap関数があり、関数プロトタイプが無いのでコンパイルエラーになるはずなのにならない (2)値渡しのはずなのに参照渡しと同じ結果になる よろしくお願いします。

  • ポインタの疑問点

    ポインタで分からないことがあります。 void swap(int* x, int* y){ int tmp; tmp = *x; *x = *y; *y = tmp; } /* int main(){ int *pA,*pB; *pA=5; *pB=10; cout << *pA << " , " << *pB <<"\n"; swap(pA,pB); cout << *pA << " , " << *pB <<"\n"; } */ int main(){ int a,b; a=5; b=10; cout << a << " , " << b <<"\n"; swap(&a,&b); cout << a << " , " << b <<"\n"; } 上のメイン関数ではエラーが起きます。どうしてなんでしょう? 下のと意味は同じだと思うのですが・・・

  • 合計値を求める関数

    #include<iostream> using namespace std; //sum関数の定義 int sum(int x, int y) { return x + y;  } int main() { int num1, num2, ans; cout << "1番目の整数を入力して下さい。\n"; cin >> num1; cout << "2番目の整数値を入力して下さい。\n"; cin >> num2; ans = sum(num1, num2); cout << "合計は" << ans << "です。\n"; return 0; }  ここのreturn x+y;の所の合計値を戻り値として返す処理の仕組みを解りやすく教えて欲しいです、戻り値はちょっと解りづらいです、よろしくお願いします。

  • mainの外に変数 vs ポインタ渡し

    C++についての質問です。プログラミング初心者ですが、よろしくお願いします。 最近、関数の外側でも変数を宣言できることを知りました。関数の外側で変数を宣言すると、全ての関数でその変数にアクセスすることができ大変便利なように思います。 「わざわざポインタ渡しなどする必要はないのでは?」と思ってしまいました。 これは何か問題があるのでしょうか? 初心者の言葉で説明しても理解しにくいかと思いますので、例として「足し算するプログラム」を以下に記載します。 ポインタ渡しで書くと、以下のような感じになるかと思います。 //●ポインタ渡し #include "stdafx.h" #include <iostream> void func(int x,int y,int *pans){ *pans = x+y; } void main(){ int a=10, b=20, ans; func(a,b,&ans); std::cout << ans << std::endl; } しかし、mainの外に変数を宣言すれば //●mainの外に変数 #include "stdafx.h" #include <iostream> int a,b,ans; void func(int x,int y){ ans = x+y; } void main(){ a=10; b=20; func(a,b); std::cout << ans << std::endl; } ansをポインタ渡しする必要なく、funcの計算結果をansに代入できました。 「●mainの外に変数」のプログラムはどのような問題や危険性を孕んでいるのでしょうか? 以上になります。長文お読みいただきありがとうございました。 よろしくお願いいたします。

  • インライン関数の使い道と理屈

    #include <iostream> using namespace std; //max関数の定義 inline int max(int x, int y){if(x>y) return x; else return y;} int main(){ int num1, num2, ans; cout << "1番目の整数を入力して下さい。\n"; cin >> num1; cout <<"2番目の整数を入力して下さい。\n"; cin >> num2; ans = max(num1, num2); cout << "最大値は" << ans << "です。\n"; return 0; } インライン関数の処理は呼び出し部分に埋め込まれるので、プログラムの処理速度が 向上することがありますとあるんですが、 どのような時にインライン関数は使用するのでしょうか? 理由もしくみもご教示お願いします。

  • 【C++】関数からクラスに変更するには?

    いつも大変お世話になっています。 VC++初心者です。 関数をクラス化していきたいのですが、具体的にどのようにしたら良いか ご指導頂けませんでしょうか。 例えば、このようなソースがあった場合、どのようにクラス化させるのでしょうか。 (また、下記の例ですと、pulsとsubで1つのグループ、 goodMoringとgoodNightで1つのグループにさせる場合には どうすれば宜しいでしょうか。) //======================= //Tool.hの中身 //======================= int plus(int x, int y); int sub(int x, int y); void goodMorning(); void goodNight(); //======================= //Tool.cppの中身 //======================= #include <iostream.h> int plus(int x, int y){ return x + y; } int sub(int x, int y){ return x - y; } void goodMorning(){ cout << "おはよう\n"; } void goodNight(){ cout << "こんばんは\n"; } //======================= //Main.cppの中身 //======================= #include <iostream.h> #include "Tool.h" int main(){ int a = puls(1,1); cout << a <<'\n'; int b = puls(2,1); cout << b <<'\n'; goodMorning(); goodNight(); }

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

    参照渡し と ポインタ渡し はどういう時に使い分けるんですか? VOID型の自作関数内でメインのブール値を書き替えたいんだけど #include <iostream.h> void ref( int &b ) { b = false; } void ptr( int *b ){ ( *b ) = true; } main(){  bool b = true;  ref( b );  cout << b;  ptr( &b );  cout << b; } だとコンパイルエラーでした。 うまくいくソースを教えてください。

  • 関数形式マクロ

    type型の二つの値を交換する関数形式マクロ swap(type,a,b)を定義せよ 例えばint型でx、yに5、10があたえられているとき、swap(int,x,y)を 呼び出した後は、x,yには10と5が格納されていなければならない。 ・・という問題で以下のようにswapを作ったのですがエラーがでます どこが問題か教えていただけないでしょうか? #include <stdio.h> #define swap(type,a,b) (m = a a = b b = m) int main(void) { int x = 1,y = 2,m; swap(int,x,y); printf("x=%d y=%d\n",x,y); return(0); }

  • ポインタ渡しについて

    関数の引数をint型のポインタで出力し、その関数を呼び出し側で値を取得するにはどうしたらいいのでしょうか? 一応ソースを作成しました(下記参照)が、ほしい値が出てきません。 よろしくお願い致します。 ----------------------------------------------- #include <stdio.h> int check(int *num){ int n=10; num = &n; return 0; } int main() { int m_num; check(&m_num); printf("%d\n",m_num); return 0; } ----------------------------------------- m_numに、10が格納されません。 check()でアドレス渡しをしたのですが・・・。 どうすれば、main関数で、数値を扱うことが出来ますか? よろしくお願い致します。

専門家に質問してみよう