C++ - возврат x, y; в чем смысл?

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

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

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

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

18 ответов


оператор запятой в основном используется в for утверждения типа so:

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

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


по словам C FAQ:

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

e1, e2

is " оцените подвыражение 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)

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

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


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

 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


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

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


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

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

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

int foo()
{
  return 20;
}

этот синтаксис можно использовать для сохранения дополнительных скобок области if- заявление. Е. Г. как правило, вы должны написать следующее:

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

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

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

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


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

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

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


нет смысла в этом заявлении return.

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

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

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


с одной стороны, это могло бы быть честной ошибкой со стороны писателя.

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

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


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


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

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

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


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

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


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

}

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

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

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


при использовании 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

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

точка является побочным эффектом x (т. е. левой стороны оператора запятой). См., например, ответ Justin Ethier для деталей.

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

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

вот пример кода Патрис Ройс "ситуация исключения" на CppCon 2016:

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