С++ - return x, y; В чем смысл?
Я программировал на C и С++ в течение нескольких лет, и теперь я только сейчас беру курс обучения в колледже, и наша книга имела такую функцию, как это для примера:
int foo(){
int x=0;
int y=20;
return x,y; //y is always returned
}
Я никогда не видел такого синтаксиса. Фактически, я никогда не видел оператора ,
, используемого вне списков параметров. Если y
всегда возвращается, то какая точка? Есть ли случай, когда нужно было бы создать оператор возврата?
(Кроме того, я отметил C также, потому что он применим к обоим, хотя моя книга специально является С++)
Ответы
Ответ 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;
}