質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

1417閲覧

値渡しと参照渡しに関しての疑問

Watching

総合スコア56

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2020/09/28 00:51

編集2020/09/28 01:10

値渡しと参照渡しに関して疑問があります。

c++

1int func(int i){return ++i;} 2int func2(int& i){return ++i;}

このような関数を定義したとします。
ここで、関数を呼び出すとき、

c++

1int main() 2{ 3 int a = 0; 4 cout << func(a) << endl; 5 cout << a << endl;//a = 0 6 cout << func2(a) << endl; 7 cout << a << endl;//a = 1 8}

というようにすると、どちらの関数も同じように引数を代入したのに、func2では渡した引数が変更されてしまいます。
これでは、値渡しを意図して引数を渡したのに、帰ってきたときには中身が変わってしまっている、というようなことが起きてしまいます。
func2 を呼び出すときには、 func(&a) と書かれるべきなのではないでしょうか?
また、このような間違いが起こらない方法はないのでしょうか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

また、このような間違いが起こらない方法はないのでしょうか。

変更されては困る、値を渡したいと思うなら、
func2(0+a); や func2(1*a); のように式を書いて値を渡すようにすれば、
参照引数はコンパイルエラーになります。

投稿2020/09/28 02:54

kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

値渡しを意図して引数を渡した

これが間違いでしょう.

「関数の引数や戻り値の型や意味を把握して → 関数を使う」という順序になるハズ
(だよね? 「とりあえず何なのかわかんねぇけど渡してみるか」とはならない)
のだから「値渡しを意図」している時点でもうダメ.

投稿2020/09/28 00:55

fana

総合スコア11996

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Watching

2020/09/28 01:04

しかし、確認ミスや何かの間違いで、本来変更されてはいけない変数を渡してしまうというミスが起こりうるのではないかと思います。勿論、関数の中身を全て確認して間違いなく記述できれば問題ありませんが、ミスは起こりえます。そして、それはインテリセンスやコンパイラが指摘してくれることはありません。 ポインタ渡しは明示的に記述する必要があり、中身が変更されることに対してある意味の確認がありますが、参照渡しはそうではありません。 そういう間違いが起こらない方法ってないんでしょうか。
maisumakun

2020/09/28 01:10

> そういう間違いが起こらない方法ってないんでしょうか。 そこまで気にするのであれば、明示的にポインタを受け取ればいいのではないでしょうか?C++はそこまで新設な言語ではありません。
Watching

2020/09/28 01:17

私が最後にc++を触ったのは10年前でした。当時に比べれば、c++は非常に親切な言語に変わったと思います。間違いの起きないように設計された新しい機能を触るたびに、感動します。 いつか、参照渡しが明示的に書けるようになり、それが推奨される日が来ることを願っています。当分は、値が変更される関数の場合はポインタを利用しようと思います。
maisumakun

2020/09/28 01:19

> いつか、参照渡しが明示的に書けるようになり、それが推奨される日が来ることを願っています。 世間の趨勢はその逆の方向に向かっています。PHPでも、5.4から渡す側の参照表記は「書けなく」なりました。
Watching

2020/09/28 01:31

C#ではrefを利用することで参照を明示的に書く必要があって、C#はC++の後継言語なので、C#の仕様が逆輸入される可能性は大いにあるのではないかと思っています。 私はPHPのことはわかりませんが、一つの言語の例だけ取り出して、世間の趨勢とまで言ってしまうのは主語が大きすぎるのではないかと思います。 勿論、そういう例があるわけで、永遠に実装されない可能性も高いと思います。ですが、私としては参照渡しに関してそのような変更が行われた方がうれしいなぁ、というわけです。
maisumakun

2020/09/28 02:02 編集

explicitなコンストラクタしか持たないReference<T>のような型を宣言して、引数はそれを受け取るようにする、そしてref()関数でReference<T>を生成するような形にすれば、現行の文法でも似たようなことは可能かと思います。 (もっとも、そこまで重厚に実装して有用かといえば、疑問符は付きます)
fana

2020/09/28 01:59 編集

引数を const参照 とすることで「書き換えないよー」と利用側に伝えることができます. 今回の func2() のような constでない参照を引数にしているものは,その宣言によって「内容を変更する意図がある」旨を利用側に明確に伝えていることになると思います. なので,利用する側が「変わらないハズ」と考えて使うのが間違い. > C#ではrefを利用することで参照を明示的に書く必要が そこはちょっと誤解がありそうです. C#の「参照型」は,上記のC++のようなconstすらも無く,「帰ってきたときには中身が変わってしまっている」ような物なのか否かに関して区別することもできず,地獄の様相だと思います.
ozwk

2020/09/28 02:45

> C#の「参照型」は,上記のC++のようなconstすらも無く,「帰ってきたときには中身が変わってしまっている」ような物なのか否かに関して区別することもできず,地獄の様相だと思います. なぜいきなりC#の参照型の話に? 参照渡しの話ではなく?
Zuishin

2020/09/28 02:58 編集

参照型をイミュータブル扱いで渡したいという話でしょう。集合であれば IEnumerable<T> や IReadOnlyList<T> で受け取ることが引数を変更しない意志表現になりますか。要素のプロパティは変更できますが。 次世代の C# では Records が使えるので、なるべくそれを生かして参照透過な関数を使うコードになるかもしれません。
fana

2020/09/28 03:24

Func( arg ); という呼び出しコードからでは,argの内容が変更されるのか否かがわからないし,その点に関してプログラマがミスったとしてもコンパイラも何も言わない という話に関して,この点においてC++はダメなのであって,C#ならそんなことは起こらない. …という話に見えたので, その辺に関して言えば,constという意思表示がある分だけC++の方がまだマシじゃねぇかな,とか. 余計な話だったようで,申し訳ない限り.
guest

0

func2 を呼び出すときには、 func(&a) と書かれるべきなのではないでしょうか?

そう書くと、ポインタ値を値渡しにする意味になります。

投稿2020/09/28 00:54

maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2020/09/28 00:55

引数をint&で宣言してあるということは、「引数を書き換える」ことを含意していますので、「値渡しを意図して引数を渡」すこと自体が間違いです。
maisumakun

2020/09/28 01:16 編集

> また、このような間違いが起こらない方法はないのでしょうか。 ミュータブルな参照引数を使わず、返り値でやり取りする
yumetodo

2020/09/28 01:33

返す側はstd::tupleがあり受け取る側は構造化束縛がある今日このごろですしねぇ
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問