• 締切済み

参照渡し と ポインタ渡し

参照渡し と ポインタ渡し はどういう時に使い分けるんですか? 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; } だとコンパイルエラーでした。 うまくいくソースを教えてください。

  • A__
  • お礼率59% (194/328)

みんなの回答

  • hogeta
  • ベストアンサー率14% (4/28)
回答No.2

#include <stdio.h> // どちらも引数をインクリメントする void ref(int a){a++;} void ptr(int* a){(*a)++;} int main() { int a = 0; ref(a); --> aの値は変わらない printf("%d\n",a); -->0が出力 ptr(&a); --> aの値は変わる printf("%d\n",a); -->1が出力 returen 0; } 簡単に言えば, 参照渡しはaの値をコピーして渡します. ポインタ渡しは, aのアドレスをコピーして渡します. なので, 参照で渡された引数をいくらいじったところで 呼出し元のaと別物ですから反映されません. ポインタ渡しにすれば, 結局はおなじ変数を見ていることに なるので, 呼出し元のaにも影響を及ぼすことになります. つまり, 2種類の引数の渡し方は, 値の変更を呼出し元へ 反映させるか否かで使い分けることになります.

A__
質問者

補足

void ref( int a ){ a++; } だと、main に戻ったときに a の値に変化がないのは分かるけど ref( a ); で呼び出して void ref( int &a){ a++; } にすると、a は変化します。これは何渡しというんですか?

  • zzzzzz
  • ベストアンサー率61% (70/113)
回答No.1

refとptrの引数の型が各々bool&とbool*である必要があります。 このままの関数定義で無理矢理キャストを行って実行すると、 不正なメモリアクセスが発生する危険が高いです。 (boolの実装によりますが。VCは5より前とそれ以降でsizeof(bool)が異なるそうです)

A__
質問者

お礼

ありがとうございます。 元々intだったソースをboolに書き替えたんだけど、 2行目と3行目の、引き数の型を書き替えるのを忘れていました。

関連するQ&A

  • 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の外に変数」のプログラムはどのような問題や危険性を孕んでいるのでしょうか? 以上になります。長文お読みいただきありがとうございました。 よろしくお願いいたします。

  • 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)値渡しのはずなのに参照渡しと同じ結果になる よろしくお願いします。

  • 参照渡しの速度について

    内部の質問なのですが、 下の簡単な例を見てください。 #include <iostream> using namespace std; //構造体 struct data { int a,b,c; }; //グローバル変数 data data1; //関数 void set_data( data &dt ) { data1 = dt;//この部分について質問 } data get_data( void ) { return data1; } int main( void ) { data d1; d1.a = 1; d1.b = 2; d1.c = 3; set_data( d ); data d2 = get_data(); cout << d2.a << d2.b << d2c << endl; return 0; } ほんとに今適当に作った変なプログラムですが無いよりはましだと思い 書いときました。 //この部分について質問 のところなのですが、これはアドレスを渡しているのでしょうか? 普通の値渡しは 内部で data1.a = dt.a; data1.b = dt.b; data1.c = dt.c; が行われていると聞いた事があるのですが、 今回の場合もそうなのでしょうか? それともアドレス渡しのように アドレスを一つ渡すだけで早い処理が出来るのでしょうか? どなたか詳しい方お願いします。

  • 文字列の一致を確認する条件分岐でエラーなります。

    どこが間違ってるのでしょうか? #include <iostream> using namespace std; int main(void) { int buffA = 1; int buffB = 10; if(buffA == buffB) { // 一致なら"true"を出力 cout << "true" << "\n"; } else { // 不一致なら"false"を出力 cout << "false" << "\n"; } return 0; } エラー内容----------------------------------- エラー: プログラム内に逸脱した '\201' があります エラー: プログラム内に逸脱した '@' があります

  • 【C++】関数ポインタの使い方

    関数ポインタの使い方で悩んでいます。 下記の (1)のようにグローバルメソッドとして定義したメソッドを関数ポインタに代入することは出来るのですが、 (2)のようにクラスのメンバメソッドとして定義したメソッドは関数ポインタに代入することは出来ませんでした。 Error:バインドされた関数へのポインターは関数の呼び出しにのみ使用できます。 というエラーが発生します。 関数ポインタに外部参照でメソッドを代入することは出来ないのでしょうか? -----(1)------------------------------------------------------------------ #include "stdafx.h" #include <iostream> using namespace std; int f(int a, int b){ return a * b; } int _tmain(int argc, _TCHAR* argv[]) { typedef int (* FUNC_POINTER)(int, int); FUNC_POINTER fp; fp = f; cout << fp(1,2) <<endl; getchar(); return 0; } ------------------------------------------------------------------------- -----(2)------------------------------------------------------------------ #include "stdafx.h" #include <iostream> using namespace std; class MPointerList{ public: int f(int a, int b){ return a * b; } }; int _tmain(int argc, _TCHAR* argv[]) { typedef int (* FUNC_POINTER)(int, int); FUNC_POINTER fp; //fp = f; MPointerList mP; fp = mP.f; cout << fp(1,2) <<endl; getchar(); return 0; } -------------------------------------------------------------------------

  • 参照渡しの間違ったコードの謎?

    現在、C++勉強中の初心者です。テキストの練習問題で値呼び出しと参照呼び出しを比較する問題に取組中に、以下のような間違ったコードを書いてしまいました。 (参照渡しのコードで、返値を設定してしまいました) ---------------------------------------- #include<iostream.h> int tripleCallByValue(int); int tripleByReference(int &); main(){ int count; cout << "count = " ; cin >> count; cout << "コピー: " << count << "\t" << tripleCallByValue(count) << endl; cout << "参照 : " << count << "\t" << tripleByReference(count) << endl; cout << "コピー: " << count << "\t" << tripleCallByValue(count) << endl; cout << "参照 : " << count << "\t" << tripleByReference(count) << endl; return 0; } int tripleCallByValue(int num){ return num *= 3; } int tripleByReference(int &num){ return num *= 3 ; } ---------------------------------------- 入力値を3倍するプログラムで、3を入力した場合の結果は   仮引数  返値 コピー  3     9 参照  9   9 コピー 9   27 参照  27   27 となりました。(Borland C++コンパイラ使用) わからないのは、2行目の参照渡しの仮引数が'9'であることです。1行目は値渡しなので、仮引数は影響を受けず、'3'が次の参照渡しの仮引数として使用されるとおもってました。 何が起こっているのか、まったく理解できません。これは、意味のある間違いでしょうか?だとしたら、どんな処理が行われた結果でしょうか? 解説よろしくお願いします。

  • wsprintf( ポインタ , "%d" , "123" );

    char str[100]; char *ptr; wsprintf(str, "%d", "1234567"); と wsprintf(ptr, "%d", "1234567"); について、 TextOut(hDC,0,10,str,lstrlen(str)); TextOut(hDC,0,30,ptr,lstrlen(ptr)); で出力したいんだけど、str ならできたけど、 ptr の方が文字化けしていました。 lstrlen(ptr); がいけないのかと思って、 その値を調べたら 0 でした。 strlen( ) はポインタに対応していると思いました。 #include <iostream.h> main(){ char *p = "あいう"; cout << strlen(p); } で 6 だったから。 Win32 の lstrlen( ) はポインタに対応していないんですか?

  • isdigitの挙動について

    #include <iostream> #include <ctype.h> using namespace std; int main() { int i = 100; if (isdigit(i)){ cout << "true"; }else{ cout << "false"; } return 0; } というプログラムを実行したのですが、falseが標準出力に表示されます。 i=100なので、isdigitでtrueが返ってくるのだと思っていたのですが、なぜfalseが帰ってくるのでしょうか?? どなたか詳しい方いらっしゃったらご教示いただけると幸いです。

  • 【C++】関数ポインタの代入

    C++の関数ポインタについて質問です。 下記のように関数ポインタを宣言し、3通りの代入を行ってみました。 (3)のように関数名の頭に&を付けた場合と(2)のように&を付けなかった場合で 全く動きが同じになってしまうのですが、何故なのでしょうか? ------------------------------------------ #include "stdafx.h" #include <iostream> using namespace std; void Func1(){ cout<<"Func1が呼ばれました。"<<endl; return; } int main() { //(1) void (*fp1_1)(); fp1_1 = Func1; fp1_1(); //(2) void (*fp1_2)()=Func1; fp1_2(); //(3) void (*fp1_3)()=&Func1; fp1_3(); getchar(); return 0; }

  • shared_ptr クラスについて

    shared_ptrクラスを使いたいのですが、使えません、どうしてでしょうか?ソースはこれです。 #include<iostream> #include <string> #include <fstream> #include<memory> using namespace std; class SMonster{ string name; int power; public: SMonster(); SMonster(int p); ~SMonster(){ }; void SetPower(int p); int GetPower(SMonster& t)const; void walk(const string& str); int GetPoint(void)const; }; class B {}; class D : public B {}; int main(void) { shared_ptr<D> sp0(new D); SMonster m(200); SMonster n(100); std::cout<<m.GetPower(m)<<std::endl; std::cout<<n.GetPower(n)<<std::endl; ShowWindow(10); }

専門家に質問してみよう