C ++ - вернуть x, y; Какой смысл? - PullRequest
46 голосов
/ 29 марта 2010

Я программировал на C и C ++ в течение нескольких лет, и сейчас я просто учусь на курсах в колледже, и в нашей книге была приведена такая функция, например:

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

Я никогда не видел такой синтаксис. На самом деле, я никогда не видел оператора ,, используемого вне списков параметров. Если y всегда возвращается, тогда какой смысл? Есть ли случай, когда необходимо будет создать инструкцию возврата, как это?

(Кроме того, я также пометил C, потому что это относится к обоим, хотя моя книга специально написана на C ++)

Ответы [ 18 ]

51 голосов
/ 29 марта 2010

Согласно C FAQ :

Точно указано значение оператора запятой в общем выражении

e1, e2

- это «вычислить подвыражение e1, затем оценить e2; значение выражения - это значение e2». Следовательно, e1 лучше включать в себя присваивание или приращение ++, или уменьшение - или вызов функции, или какой-либо другой вид побочного эффекта, потому что в противном случае он вычислит значение, которое будет отброшено.

Так что я согласен с вами, нет смысла , кроме как для иллюстрации того, что это правильный синтаксис, если таковой.

Если вы хотите вернуть оба значения в C или C ++, вы можете создать struct, содержащий x и y членов, и вместо этого вернуть структуру:

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 ++. Хотя, как предлагает Марк ниже, в C ++ вы можете определить конструктор для структуры point, который дает более элегантное решение.

<ч />

Кстати, возможность прямого возврата нескольких значений замечательна в таких языках, как Python, которые ее поддерживают:

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

>>> foo()
(0, 20)
23 голосов
/ 29 марта 2010

Запятая в списках параметров используется только для разделения параметров и не совпадает с оператором запятой. Оператор запятой, как в вашем примере, вычисляет и x, и y, а затем выбрасывает x.

В этом случае я бы предположил, что это ошибка человека, который пытается вернуть два значения и не знает, как это сделать.

20 голосов
/ 29 марта 2010

Оператор запятой в основном используется в for инструкциях, например:

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

Первая запятая не является оператором запятой, это часть синтаксиса объявления. Второй - это оператор запятой.

9 голосов
/ 29 марта 2010

Это на самом деле не отвечает на первоначальный вопрос, но может быть интересным для некоторых людей, но если вы хотите, чтобы он возвращал оба в 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);
8 голосов
/ 29 марта 2010
 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;
 }

: р

5 голосов
/ 29 марта 2010

Так же, как все, кто комментирует здесь, думают, что это бессмысленно, и я не согласен, просто глядя на пример, я собираюсь сделать предположение, что это не намного лучше:

Автор получал предупреждение компилятора о том, что x не используется внутри функции, и это был простой способ убрать предупреждение.

4 голосов
/ 24 июля 2012

Этот синтаксис может использоваться для сохранения дополнительных квадратных скобок оператора if -. Например. обычно вы пишете следующее:

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

Это может быть заменено следующим:

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

Я думаю, что использование этого стиля кодирования скорее мотивировано желанием позировать, чем писать чистый код.

4 голосов
/ 29 марта 2010

Это оператор запятой (,) .

Оба выражения x и y вычисляются. Результатом всего выражения является y, то есть последнее значение.

Трудно сказать, почему это используется здесь. Я думаю, для демонстрационных целей. Очевидно, что функцию можно изменить на:

int foo()
{
  return 20;
}
3 голосов
/ 29 марта 2010

Это похоже на ужасный пример кода.Это может быть допустимый синтаксис в C / C ++, но я не могу придумать причину, почему вы когда-нибудь захотите это сделать.

Если вы хотите вернуть x и y, лучший способ сделать этов C ++ было бы определить класс или структуру Point с помощью свойств x и y и вернуть их.Другой вариант - передать x и y по ссылке, а затем соответствующим образом установить значения в методе.

Если метод просто вернет y, я просто "верну y;".Если x нужно «оценить» перед оператором return, это должно быть сделано в отдельной строке.

2 голосов
/ 29 марта 2010

Нет смысла в этом операторе возврата.

Если бы x было объявлено volatile, это вызвало бы доступ (поскольку, по крайней мере, в C ++ ссылки на volatile переменные считаются внешне наблюдаемым поведением), но это не так.

Если бы вместо x был какой-то расчет с побочными эффектами, он бы выполнил этот расчет и затем возвратил y. Тем не менее, не volatile x не имеет побочных эффектов. Реализация не обязана выполнять любой код, который не имеет побочных эффектов или наблюдаемого извне поведения. Оператор запятой выполняет все, что находится слева от запятой, игнорирует результат, выполняет и сохраняет значение правой стороны (за исключением того, что в этом случае он может игнорировать левую часть оператора).

Следовательно, оператор return x, y; - это то же самое, что и return y;. Если бы x было не просто бессмысленным исполнением, было бы лучше стилистически записать его как x; return y;, что точно так же. Это было бы не так запутанно.

...