Подтвердить что ты не робот

С++ - return x, y; В чем смысл?

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

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

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

В соответствии с C FAQ:

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

e1, e2

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

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

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


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

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

>>> foo()
(0, 20)

Ответ 3

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

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

Ответ 4

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

Ответ 5

 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;
 }

: р

Ответ 6

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

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

Ответ 7

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

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

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

int foo()
{
  return 20;
}

Ответ 8

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

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

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

Ответ 9

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

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

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

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

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

Ответ 10

В этом операторе return нет смысла.

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

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

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

Ответ 11

С одной стороны, это может быть честная ошибка со стороны автора.

С другой стороны, писатель может объяснить синтаксически правильный правильный код, а также предупреждения компилятора.

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

Ответ 12

Это оператор запятой. Такой синтаксис можно использовать для отключения предупреждения от компилятора о неиспользуемой переменной x.

Ответ 13

За пределами циклов другой главный пользователь этого оператора comman (как и версия версии функции) находится в макросах, которые возвращают значение после выполнения некоторых действий. Это другие способы сделать это сейчас, но я думаю, что оператор comman был самым чистым способом.

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

Обратите внимание, что этот макрос является плохим примером макросов вообще, потому что он повторяет x и, вероятно, по другим причинам. Использование оператора запятой таким образом должно быть редкими. Пример из вашей книги, вероятно, был попыткой сделать пример кода подходящим в пределах количества строк, доступных для этого примера.

Ответ 14

Есть ли случай, когда нужно было бы создать оператор return?

IMO, я бы никогда не использовал несколько возвратов в функции, подобной примеру книги. Это нарушает структурированный дизайн. Тем не менее, есть много программистов! Отладка кода другого пользователя Я назначил значение глобальной переменной в каждом возвратном выражении, чтобы я мог выяснить, какой результат выполнен.

Ответ 15

Я видел этот синтаксис, используемый в 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;

}

Ответ 16

Книга пытается устранить потенциальную путаницу людей, которые изучали другие языки до С++. На многих языках вы можете возвращать несколько значений с использованием аналогичного синтаксиса. В С++ он будет компилироваться без предупреждения (если вы не укажете -Wall или -Wunused-value), но он не будет работать так, как вы могли бы ожидать, если бы вы привыкли к этим другим языкам. Он просто вернет последнее значение.

Однако, похоже, автор вызвал больше путаницы, чем он предотвратил, поскольку нет читаемой ситуации для использования такого синтаксиса в операторе return в С++, за исключением случайного использования его, как другого языка. Он предупреждает об использовании, которое не было бы у большинства людей. Если бы вы это сделали, было бы сложно запутать debug, поскольку команда множественного присваивания int x, y = foo() также компилируется просто отлично.

Нижняя строка: всегда используйте -Wall и исправьте, о чем она вас предупреждает. Синтаксис С++ позволяет писать много вещей, которые не имеют смысла.

Ответ 17

При использовании с ключевым словом return оператор запятой возвращает значение last, которое изначально запутывает, но может сделать вещи более краткими.

Например, следующая программа выйдет со статусом 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

Ответ 18

Если y всегда возвращается, то какая точка?

Точка - это побочный эффект x (т.е. левой части оператора запятой). См. Джастин Этье отвечает за подробности.

Есть ли случай, когда нужно будет создать оператор return?

Пример для функции constexpr в С++ 11 до С++ 14: такая функция может не содержать произвольных операторов, но ровно один оператор return,

Вот пример кода из Patrice Roys "Исключение ситуации" на CppCon 2016:

constexpr int integral_div(int num, int denom) {
    return assert(denom != 0), num / denom;
}