简体   繁体   English

C ++ - 返回x,y;有什么意义?

[英]C++ — return x,y; What is the point?

I have been programming in C and C++ for a few years and now I'm just now taking a college course in it and our book had a function like this for an example: 我已经用C和C ++编程了几年,现在我刚刚开始学习大学课程而且我们的书有一个这样的函数作为一个例子:

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

I have never seen such syntax. 我从未见过这样的语法。 In fact, I have never seen the , operator used outside of parameter lists. 事实上,我从来没有见过的,参数列表之外使用运营商。 If y is always returned though, then what is the point? 如果y总是返回,那么重点是什么? Is there a case where a return statement would need to be created like this? 是否有需要像这样创建return语句的情况?

(Also, I tagged C as well because it applies to both, though my book specifically is C++) (另外,我也标记了C,因为它适用于两者,尽管我的书特别是C ++)

According to the C FAQ : 根据C FAQ

Precisely stated, the meaning of the comma operator in the general expression 准确地说,逗号运算符在一般表达式中的含义

e1 , e2 e1,e2

is "evaluate the subexpression e1, then evaluate e2; the value of the expression is the value of e2." 是“评估子表达式e1,然后评估e2;表达式的值是e2的值。” Therefore, e1 had better involve an assignment or an increment ++ or decrement -- or function call or some other kind of side effect, because otherwise it would calculate a value which would be discarded. 因此,e1最好涉及赋值或增量++或减量 - 或函数调用或其他一些副作用,否则它将计算一个将被丢弃的值。

So I agree with you, there is no point other than to illustrate that this is valid syntax, if that. 所以我同意你的观点,除了说明这是有效的语法之外没有其他意义,如果那样的话。

If you wanted to return both values in C or C++ you could create a struct containing x and y members, and return the struct instead: 如果你想用C或C同时返回值++,你可以创建一个struct含有xy成员,并返回结构来代替:

struct point {int x; int y;};

You can then define a type and helper function to allow you to easily return both values within the struct : 然后,您可以定义类型和帮助函数,以便在struct轻松返回两个值:

typedef struct point Point;

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

And then change your original code to use the helper function: 然后更改原始代码以使用辅助函数:

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

And finally, you can try it out: 最后,你可以尝试一下:

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

This example compiles in both C and C++. 此示例在C和C ++中编译。 Although, as Mark suggests below, in C++ you can define a constructor for the point structure which affords a more elegant solution. 虽然如Mark所示,在C ++中,您可以为point结构定义构造函数,从而提供更优雅的解决方案。


On a side note, the ability to return multiple values directly is wonderful in languages such as Python that support it: 另外,在支持它的Python语言中,直接返回多个值的能力非常好:

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

>>> foo()
(0, 20)

The comma in parameter lists is just there to separate the parameters, and is not the same as the comma operator. 参数列表中的逗号仅用于分隔参数,与逗号运算符不同。 The comma operator, as in your example, evaluates both x and y, and then throws away x. 在您的示例中,逗号运算符计算x和y,然后抛弃x。

In this case, I would guess that it is a mistake by someone who tries to return two values, and didn't know how to do it. 在这种情况下,我猜想尝试返回两个值并且不知道如何操作的人是错误的。

The comma operator is primarily used in for statements like so: 逗号运算符主要用于for语句:

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

The first comma is not a comma operator, it's part of the declaration syntax. 第一个逗号不是逗号运算符,它是声明语法的一部分。 The second is a comma operator. 第二个逗号运算符。

This doesn't really answer the original question at all but might be of interest to some people, but if you wanted to it to return both in C++ you'd need to write it like this (and would need a c++0x compiler) 这根本不能回答原始问题但可能对某些人感兴趣,但是如果你想用C ++返回它们,你需要像这样写它(并且需要一个c ++ 0x编译器) )

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

The access it like this - 这样访问 -

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 :p

Much like everyone commenting here thinks it is pointless and I don't disagree, just looking at the example, I'm going to make a guess that's not much better: 就像每个评论这里的人都认为这是毫无意义的一样,我并不反对,只是看一下这个例子,我会猜测这不是更好:

The writer was getting a compiler warning about x not being used within the function, and this was an easy way to get the warning to go away. 作者正在收到关于x未在函数中使用的编译器警告,这是让警告消失的简单方法。

This syntax can be used to save additional scope brackets of an if - statement. 此语法可用于保存if语句的其他范围括号。 Eg normally you would write the following: 例如,通常你会写以下内容:

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

This can be replaced by the following: 这可以由以下内容代替:

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

I think the usage of this coding style is rather motivated by the urge for posing than for writing clean code. 我认为这种编码风格的使用是出于对冒充的冲动,而不是编写干净的代码。

This is the comma operator (,) . 这是逗号运算符(,)

Both expressions x and y are evaluated. 表达式x和y都被计算。 The result of the overall expression is y, ie, the latter value. 整体表达的结果是y,即后一个值。

It's hard to say why it is used here. 很难说为什么在这里使用它。 I guess, for demonstration purposes. 我想,出于演示目的。 Clearly the function could be refactored to: 显然,该功能可以重构为:

int foo()
{
  return 20;
}

That looks like a terrible example of code. 这看起来像是一个可怕的代码示例。 It might be valid syntax in C/C++, but I can't think of a reason why you'd ever want to do that. 它可能是C / C ++中的有效语法,但我想不出你为什么要这样做的原因。

If you want to return both x and y, a better way to do it in C++ would be to define a "Point" class or struct with x and y properties, and return that. 如果要返回x和y,在C ++中更好的方法是使用x和y属性定义“Point”类或结构,并返回它。 Another option would be to pass in x and y by reference, then set the values appropriately in the method. 另一种选择是通过引用传入x和y,然后在方法中适当地设置值。

If the method is going to just return y, I would just "return y;". 如果方法只是返回y,我只会“返回y;”。 If x needs to be "evaluated" before the return statement, it should be done on a separate line. 如果x需要在return语句之前“评估”,则应该在单独的行上完成。

There is no point in that return statement. 返回声明没有意义。

If x were declared volatile , it would force an access (since at least in C++ references to volatile variables are considered to be externally observable behavior), but it isn't. 如果x被声明为volatile ,它将强制访问(因为至少在C ++中对volatile变量的引用被认为是外部可观察的行为),但事实并非如此。

If, instead of x , there was some sort of calculation with side effects, it would do that calculation and then return y . 如果不是x ,而是存在某种带副作用的计算,它会进行该计算,然后返回y However, a non- volatile x has no side effects. 然而,非volatile x没有副作用。 The implementation is not required to execute any code that has no side effects or externally observable behavior. 执行不需要执行任何没有副作用或外部可观察行为的代码。 The comma operator executes whatever is on the left side of the comma, disregards the result, and executes and keeps the value of the right side (except that it's free to ignore the left side of the operator in this case). 逗号运算符执行逗号左侧的任何内容,忽略结果,并执行并保留右侧的值(除非在这种情况下可以忽略运算符的左侧)。

Therefore, the return x, y; 因此, return x, y; statement is the exact same thing as return y; 声明与return y;完全相同return y; . If x wasn't just a completely meaningless thing to execute, it would be stylistically better to write it as x; return y; 如果x不仅仅是一个完全没有意义的事情,那么将它写成x; return y;会在风格上更好x; return y; x; return y; , which is the precise same thing. ,这是完全相同的事情。 It wouldn't be nearly as confusing that way. 它不会那么令人困惑。

On the one hand, it could be an honest mistake on the part of the writer. 一方面,作者可能是一个诚实的错误。

On the other hand, the writer might be explaining syntactically correct correct code, versus compiler warnings. 另一方面,作者可能正在解释语法上正确的正确代码,而不是编译器警告。

Either way, the only way to return multiple results would be to define a class and use its instance, or perhaps an array or collection. 无论哪种方式,返回多个结果的唯一方法是定义一个类并使用它的实例,或者可能是一个数组或集合。

This is the comma operator. 这是逗号运算符。 Such syntax can be used to disable warning from compiler about unused variable x . 此类语法可用于禁用编译器关于未使用的变量x警告。

Outside of for loops the other major user of this comman operator (as apposed to the function call version) is in macros that return a value after doing some stuff. 在for循环之外,这个comman操作符的另一个主要用户(与函数调用版本相似)是在宏中,在执行某些操作后返回一个值。 These are other ways to do this now, but I think that the comman operator used to be the cleanest way. 现在这些是其他方法,但我认为comman运算符曾经是最干净的方式。

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

Please note that this macro is a bad example of macros in general because it repeats x and probably for other reasons. 请注意,这个宏通常是宏的一个不好的例子,因为它重复x并且可能由于其他原因。 Use of the comma operator in this fashion should be rare. 以这种方式使用逗号运算符应该是罕见的。 The example from your book was probably an attempt to make a code exampe fit within the number of lines available for that example. 您的书中的示例可能是尝试使代码示例适合该示例可用的行数。

I have seen this syntax used in C to do housekeeping when returning midway in an operation. 我已经看到在C中使用这种语法在操作中途返回时进行内务处理。 Definitely not maintainable code: 绝对不可维护的代码:

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;

}

The book is trying to eliminate potential confusion of people who learned other languages before C++. 本书试图消除在C ++之前学习其他语言的人的混淆。 In many languages, you can return multiple values using similar syntax. 在许多语言中,您可以使用类似的语法返回多个值。 In C++, it will compile without warning (unless you specify -Wall or -Wunused-value ), but it won't work the way you might expect if you were accustomed to those other languages. 在C ++中,它将在没有警告的情况下进行编译(除非您指定-Wall-Wunused-value ),但如果您习惯使用其他语言,它将无法按预期方式工作。 It will just return the last value. 它只会返回最后一个值。

However, it seems the author caused more confusion than he prevented, since there's no readable situation to use such syntax in a return statement in C++ except by accidentally using it like another language. 然而,似乎作者引起的混淆比他预防的更多,因为在C ++的return语句中使用这种语法是没有可读的情况,除非意外地像其他语言一样使用它。 He's warning about usage that wouldn't occur to most people to try. 他警告大多数人不会尝试使用。 If you did, though, it would be super confusing to debug, since the multiple assignment statement int x, y = foo() also compiles just fine. 但是,如果你这样做,那么调试会非常混乱,因为多重赋值语句int x, y = foo()也可以很好地编译。

Bottom line: always use -Wall and fix what it warns you about. 底线:始终使用-Wall并修复它警告你的内容。 C++ syntax allows you to write many things that don't make sense. C ++语法允许您编写许多没有意义的东西。

When used with the return keyword, the comma operator returns the last value, which is initially confusing but can make things more concise . 当与return关键字一起使用时,逗号运算符返回最后一个值,这最初会让人感到困惑,但可以使事情更简洁

For example, the following program will exit with a status code of 2. 例如,以下程序将以状态代码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;
}

When compiling and executing with the following, you will see the output below. 使用以下内容编译和执行时,您将看到下面的输出。

michael$ g++ main.cpp -o main.out && ./main.out ; echo $?
one
a
zero
2

Is there a case where a return statement would need to be created like this? 是否有需要像这样创建return语句的情况?

IMO, I would never use multiple returns in a function like the book example. IMO,我绝不会在书籍示例等函数中使用多个返回。 It violates structured design. 它违反了结构化设计。 Nevertheless, there are many programmers that do! 不过,有很多程序员可以做到! Debugging someone else's code I have assigned a value to a global variable in each return statement so I could figure out which return executed. 调试其他人的代码我已经在每个return语句中为一个全局变量赋值,这样我就可以找出执行的返回值。

If y is always returned though, then what is the point? 如果y总是返回,那么重点是什么?

The point is the side effect of x (ie of the left hand side of the comma operator). 重点是x的副作用(即逗号运算符的左侧)。 See eg Justin Ethier answer for details. 有关详细信息,请参阅Justin Ethier答案。

Is there a case where a return statement would need to be created like this? 是否有需要像这样创建return语句的情况?

An example is for a constexpr function in C++11 until C++14: such a function may not contain arbitrary statements, but exactly one return statement. 一个例子是C ++ 11中的constexpr函数,直到C ++ 14:这样的函数可能不包含任意语句,而只包含一个return语句。

Here is a code sample from Patrice Roys “The Exception Situation" at CppCon 2016 : 以下是CppCon 2016中Patrice Roys“异常情况”的代码示例:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM