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

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

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

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

Q&A

解決済

2回答

1237閲覧

C++: 参照の挙動に関して (※式の評価順序)

reverse

総合スコア12

C++

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

2グッド

1クリップ

投稿2016/12/31 19:24

編集2018/03/13 15:54

情報が古くなっています‼ (追記参照)

参照で受け取った引数への変更を出力した際、
下記コードのように、式を分けない場合と分ける場合で出力内容が異なるようです。
どうしてこうなるのでしょうか?
両出力が同一(後者)だと想定していただけに非常に気になります。
回答の程、宜しくお願いします。

http://ideone.com/KhCDTK

cpp

1#include <iostream> 2 3template <typename T> 4T f(T& t) 5{ 6 return ++t; 7} 8 9void test1() 10{ 11 int a{}; 12 std::cout << f(a) << " " << a << std::endl; 13} 14 15void test2() 16{ 17 int a{}; 18 std::cout << f(a) << " "; 19 std::cout << a << std::endl; 20} 21 22int main() 23{ 24 test1(); 25 test2(); 26 return 0; 27}
1 0 1 1

追記 (2018.3.14)

C++17にて式の評価順が厳密に定義された(参考)為、C++17以降では両ケース共に後者の出力となるようです。ご注意ください。

mkgrei, maisumakun👍を押しています

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

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

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

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

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

guest

回答2

0

ベストアンサー

C/C++の評価順序(演算子の優先順序ではなく式の評価順序)は一部の演算子を除きコンパイラー依存の部分があると思います。例えば||, &&ですと必ず左の式が先に評価されることが保証されますが << は保証されないのだと思います。
そんなわけで、
std::cout << f(a) << a << endl;

と書くとf(a)が先に評価されるか右のほうのaが先かは保証されないということではないでしょうか。実際にやってみると自分の環境(gcc 5.4.0)で最適化オプションなどつけずにやると質問者さんと同じ結果を得ました。しかし

std::cout << f(a) << f(a) << endl;

とやると左側のf(a)が先に評価されてました。

投稿2016/12/31 21:05

編集2017/01/01 06:36
KSwordOfHaste

総合スコア18394

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

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

reverse

2017/01/01 04:28

なるほど、コンパイラレベルでの問題だったんですね。 コンパイラの処理については無知なので、一つ知識が増えて良かったです。 回答ありがとうございました!
KSwordOfHaste

2017/01/01 05:20

より正確には言語仕様が「どっちをさきに評価してもいいよ」となっているということだと思います。言語仕様で評価順序が規定されていればコンパイラも当然それに従います。あえてそれを規定せずにコンパイラーの工夫の余地を残した言語仕様にしたということだと思います。
guest

0

参照の挙動もそうですが、値の評価(処理)が右からです。
この辺は「operator 演算子」や 関数の作り方等で処理順番が見た目から想像できないこともあると思うので、
関数などに渡す前に処理を終わったものを渡すようにしたほうが後々楽になると思います。
(誰かが作った関数だと思ったら「マクロ関数」だったりする場合も含めて・・・)

それぞれの test 関数の置き換えとコメントつけてみました。

test1()

C++

1std::cout << 1 << " " << 0 << std::endl; // int a{}; の 0 が先に右に入っている。左がその後に計算されるので1

test2()

C++

1 std::cout << 1 << " "; // f(a)で処理されて a が 1 に。 2 std::cout << 1 << std::endl; // a が 1のままなので 1。

投稿2016/12/31 21:13

CerealRusk

総合スコア43

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

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

reverse

2017/01/01 04:34

たしかに、参照の挙動というよりか値の評価についての問題ですね… 別のテストケースも考えるべきでした。 改めて置き換えた式も書いてくださり、分かりやすかったです。 回答ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問