48

私は数年間CとC++でプログラミングしてきましたが、今は大学のコースを受講しているところです。たとえば、この本には次のような機能があります。

int foo(){
  int x=0;
  int y=20;
  return x,y; //y is always returned
}

私はそのような構文を見たことがありません。,実際、パラメータリストの外で使用される演算子を見たことがありません。yただし、常に返される場合、ポイントは何ですか?このようにreturnステートメントを作成する必要がある場合はありますか?

(また、私の本は特にC ++ですが、両方に適用されるため、Cにもタグを付けました)

4

18 に答える 18

53

C FAQによると:

正確に言うと、一般式でのコンマ演算子の意味

e1、e2

は「部分式e1を評価し、次にe2を評価します。式の値はe2の値です。」したがって、e1には、割り当て、インクリメント++、デクリメント、または関数呼び出しやその他の種類の副作用が含まれている方がよいでしょう。そうしないと、破棄される値が計算されるためです。

ですから、私はあなたに同意します。もしそうなら、これが有効な構文であることを説明する以外に意味はありません。

CまたはC++で両方の値を返したい場合は、struct包含メンバーxyメンバーを作成し、代わりに構造体を返すことができます。

struct point {int x; int y;};

次に、タイプとヘルパー関数を定義して、struct:内の両方の値を簡単に返すことができます。

typedef struct point Point;

Point point(int xx, int yy){
  Point p;
  p.x = xx;
  p.y = yy;
  return p;
}

次に、ヘルパー関数を使用するように元のコードを変更します。

Point foo(){
  int x=0;
  int y=20;
  return point(x,y); // x and y are both returned
}

そして最後に、あなたはそれを試すことができます:

Point p = foo();
printf("%d, %d\n", p.x, p.y);

この例は、CとC++の両方でコンパイルされます。ただし、Markが以下に示唆しているように、C ++ではpoint、より洗練されたソリューションを提供する構造体のコンストラクターを定義できます。


ちなみに、複数の値を直接返す機能は、それをサポートするPythonなどの言語では素晴らしいものです。

def foo():
  x = 0
  y = 20
  return x,y # Returns a tuple containing both x and y

>>> foo()
(0, 20)
于 2010-03-29T16:16:19.273 に答える
23

パラメータリストのコンマは、パラメータを区切るためだけにあり、コンマ演算子と同じではありません。例のように、コンマ演算子はxとyの両方を評価してから、xを破棄します。

この場合、2つの値を返そうとして、その方法がわからなかった人の間違いだと思います。

于 2010-03-29T16:13:52.277 に答える
20

コンマ演算子は、主に次のforようなステートメントで使用されます。

for( int i=0, j=10; i<10; i++, j++ )
{
    a[i] = b[j];
}

最初のコンマはコンマ演算子ではなく、宣言構文の一部です。2番目コンマ演算子です。

于 2010-03-29T16:18:42.920 に答える
9

これは実際には元の質問にまったく答えませんが、一部の人にとっては興味深いかもしれませんが、両方をC ++で返す場合は、このように記述する必要があります(c ++ 0xコンパイラが必要になります)。 )。

tuple<int, int> foo()
{
    int x = 0;
    int y = 20;
    return make_tuple(x, y);
}

このようにアクセスする-

tuple<int, int> data = foo();
int a = get<0>(data);
int b = get<1>(data);
于 2010-03-29T16:46:09.080 に答える
8
 struct Point {
   int x, y;
   Point(int x_) : x(x_), y(0) {}
   Point(const Point& p) : x(p.x), y(p.y) {}
   Point operator, (int y_) const { Point p=*this; p.y = y_; return p; }
 };

 Point get_the_point () {
    int x = 0;
    int y = 20;
    return (Point)x, y;
 }

:p

于 2010-03-29T16:27:47.127 に答える
5

ここでコメントしているすべての人がそれは無意味だと思っているのと同じように、私は同意しません。例を見るだけで、それほど良くないことを推測します。

ライターは、関数内でxが使用されていないことについてコンパイラーの警告を受け取りました。これは、警告を取り除く簡単な方法でした。

于 2010-03-29T16:26:27.083 に答える
4

これはコンマ演算子(、)です。

式xとyの両方が評価されます。全体的な式の結果はy、つまり後者の値です。

ここで使用されている理由はわかりません。デモンストレーションの目的で。明らかに、関数は次のようにリファクタリングできます。

int foo()
{
  return 20;
}
于 2010-03-29T16:13:32.933 に答える
4

ifこの構文を使用して、 -ステートメントの追加のスコープブラケットを保存できます。たとえば、通常は次のように記述します。

if (someThing == true)
{
    a = 1;
    b = 2;
    return true;
}

これは、次のように置き換えることができます。

if (someThing == true)
    return a = 1, b = 2, true;

このコーディングスタイルの使用は、クリーンなコードを書くよりもポーズをとる衝動に動機付けられていると思います。

于 2012-07-24T14:25:49.727 に答える
3

それはひどいコードの例のように見えます。これはC/C ++で有効な構文かもしれませんが、あなたがそれをやりたいと思う理由は考えられません。

xとyの両方を返したい場合、C ++でそれを行うためのより良い方法は、xプロパティとyプロパティを使用して「Point」クラスまたは構造体を定義し、それを返すことです。もう1つのオプションは、参照によってxとyを渡し、メソッドで値を適切に設定することです。

メソッドがyを返すだけの場合は、「y;を返す」だけです。xをreturnステートメントの前に「評価」する必要がある場合は、別の行で実行する必要があります。

于 2010-03-29T16:18:55.637 に答える
2

そのreturnステートメントには意味がありません。

x宣言された場合volatile、アクセスを強制します(少なくとも、C ++では、volatile変数への参照は外部から観察可能な動作と見なされるため)が、そうではありません。

の代わりにx、副作用を伴うある種の計算があった場合、その計算を実行してからを返しyます。ただし、非volatile xは副作用はありません。副作用や外部から観察可能な動作がないコードを実行するために、実装は必要ありません。コンマ演算子は、コンマの左側にあるものをすべて実行し、結果を無視して、右側の値を実行して保持します(この場合、演算子の左側を無視してもかまいません)。

したがって、return x, y;ステートメントはとまったく同じものreturn y;です。実行するのが完全に無意味なものではない場合xは、まったく同じことであると書く方がスタイル的に優れていx; return y;ます。そのように混乱することはほとんどないでしょう。

于 2010-03-29T17:02:51.380 に答える
1

一方では、それは作家の側の正直な間違いである可能性があります。

一方、ライターは、コンパイラーの警告ではなく、構文的に正しい正しいコードを説明している可能性があります。

いずれにせよ、複数の結果を返す唯一の方法は、クラスを定義してそのインスタンスを使用するか、おそらく配列またはコレクションを使用することです。

于 2010-03-29T16:41:27.737 に答える
1

これはコンマ演算子です。このような構文を使用して、未使用の変数に関するコンパイラからの警告を無効にすることができますx

于 2010-03-29T17:08:47.770 に答える
1

forループの外側では、このコンマン演算子の他の主要なユーザー(関数呼び出しバージョンとは対照的に)は、いくつかの処理を実行した後に値を返すマクロ内にあります。これらは現在これを行う他の方法ですが、コンマ演算子は以前は最もクリーンな方法だったと思います。

#define next(A, x, y, M) ((x) = (++(y))%(M) , A[(x)])

このマクロは、xを繰り返すため、またおそらく他の理由で、一般的にマクロの悪い例であることに注意してください。この方法でコンマ演算子を使用することはまれです。あなたの本の例は、おそらくその例で利用可能な行数内にコード例を収めようとする試みでした。

于 2010-03-29T19:07:00.260 に答える
0

このようにreturnステートメントを作成する必要がある場合はありますか?

IMO、本の例のような関数で複数のリターンを使用することは決してありません。構造化設計に違反しています。それにもかかわらず、そうする多くのプログラマーがいます!他の誰かのコードをデバッグする各returnステートメントのグローバル変数に値を割り当てて、どのreturnが実行されたかを把握できるようにしました。

于 2010-09-25T12:08:03.013 に答える
0

オペレーションの途中で戻るときにハウスキーピングを行うためにCで使用されるこの構文を見てきました。間違いなく保守不可能なコード:

int foo(int y){
  char *x;
  x = (char*)malloc(y+1);
  /** operations */
  if (y>100) return free(x),y;
  /** operations */
  if (y>1000) return free(x),y;

}
于 2013-09-11T09:41:21.793 に答える
0

この本は、C++より前に他の言語を学んだ人々の潜在的な混乱を排除しようとしています。多くの言語では、同様の構文を使用して複数の値を返すことができます。C ++では、警告なしにコンパイルされますが(-Wallまたはを指定しない限り-Wunused-value)、他の言語に慣れている場合は期待どおりに機能しません。最後の値を返すだけです。

ただし、誤って別の言語のように使用する場合を除いて、C ++のreturnステートメントでそのような構文を使用する読み取り可能な状況がないため、作成者は防止したよりも多くの混乱を引き起こしたようです。彼は、ほとんどの人が試してはいけない使用法について警告しています。ただし、そうすると、複数の代入ステートメントも正常にコンパイルされるため、デバッグが非常に混乱しint x, y = foo()ます。

結論:常に-Wall警告内容を使用して修正してください。C ++構文を使用すると、意味をなさない多くのことを記述できます。

于 2014-06-26T15:27:53.650 に答える
0

returnキーワードと一緒に使用すると、コンマ演算子は最後の値を返します。これは最初は混乱しますが、より簡潔にすることができます。

たとえば、次のプログラムはステータスコード2で終了します。

#include <iostream>
using namespace std;

void a() {
    cout << "a" << endl;
}


int one() {
    cout << "one" << endl;
    return 1;
}

int zero() {
    cout << "zero" << endl;
    return 0;
}

int main() {
    return one(), a(), zero(), 2;
}

以下を使用してコンパイルおよび実行すると、以下の出力が表示されます。

michael$ g++ main.cpp -o main.out && ./main.out ; echo $?
one
a
zero
2
于 2016-01-07T01:34:58.837 に答える
0

ただし、yが常に返される場合、ポイントは何ですか?

ポイントは、xの副作用(つまり、コンマ演算子の左側)です。詳細については、たとえばJustinEthierの回答を参照してください。

このようにreturnステートメントを作成する必要がある場合はありますか?

例は、C++11からC++14までのconstexpr関数の場合です。このような関数には、任意のステートメントを含めることはできませんが、returnステートメントを1つだけ含めることができます。

これは、 CppCon2016でのPatriceRoysの「TheExceptionSituation」のコードサンプルです。

constexpr int integral_div(int num, int denom) {
    return assert(denom != 0), num / denom;
}
于 2016-10-30T22:07:28.673 に答える