C++ -- 返回 x,y;重点是什么?

发布于 2024-08-26 14:28:15 字数 314 浏览 7 评论 0 原文

我已经用 C 和 C++ 编程几年了,现在我刚刚上大学课程,我们的书有一个这样的函数作为例子:

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

我从来没有见过这样的语法。事实上,我从未见过在参数列表之外使用 , 运算符。如果 y 总是返回,那还有什么意义呢?是否存在需要像这样创建 return 语句的情况?

(另外,我也标记了 C,因为它适用于两者,尽管我的书具体是 C++)

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:

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? Is there a case where a return statement would need to be created like this?

(Also, I tagged C as well because it applies to both, though my book specifically is C++)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(18

波浪屿的海角声 2024-09-02 14:28:15

根据 C 常见问题解答

准确地说,通用表达式中逗号运算符的含义

e1、e2

是“计算子表达式 e1,然后计算 e2;表达式的值是 e2 的值。”因此,e1 最好涉及赋值或递增 ++ 或递减——或者函数调用或某种其他类型的副作用,因为否则它会计算出一个将被丢弃的值。

所以我同意你的观点,除了说明这是有效的语法之外没有任何意义(如果是的话)。

如果您想在 C 或 C++ 中返回这两个值,您可以创建一个包含 xy 成员的 struct,然后返回该结构

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++ 编译。不过,正如 Mark 下面所建议的,在 C++ 中,您可以为 point 结构定义一个构造函数,这提供了更优雅的解决方案。


附带说明一下,直接返回多个值的能力对于支持它的语言(例如 Python)来说非常出色:

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

>>> foo()
(0, 20)

According to the C FAQ:

Precisely stated, the meaning of the comma operator in the general expression

e1 , e2

is "evaluate the subexpression e1, then evaluate e2; the value of the expression is the value of 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.

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:

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:

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++. Although, as Mark suggests below, in C++ you can define a constructor for the point structure which affords a more elegant solution.


On a side note, the ability to return multiple values directly is wonderful in languages such as Python that support it:

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

>>> foo()
(0, 20)
跨年 2024-09-02 14:28:15

参数列表中的逗号只是用于分隔参数,与逗号运算符不同。逗号运算符(如您的示例中所示)会计算 x 和 y,然后丢弃 x。

在这种情况下,我猜想这是一个试图返回两个值的人犯的错误,并且不知道该怎么做。

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.

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.

溺孤伤于心 2024-09-02 14:28:15

逗号运算符主要用在 for 语句中,如下所示:

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

第一个逗号不是逗号运算符,它是声明语法的一部分。第二个逗号运算符。

The comma operator is primarily used in for statements like so:

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.

纸短情长 2024-09-02 14:28:15

这根本没有真正回答最初的问题,但可能对某些人感兴趣,但如果你想让它在 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);

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)

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);
红墙和绿瓦 2024-09-02 14:28:15
 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

 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

娇女薄笑 2024-09-02 14:28:15

就像这里评论的每个人都认为这是毫无意义的,我也不反对,只要看一下这个例子,我就会猜测这并没有好多少:

作者收到了关于 x 未在函数内使用的编译器警告,这是消除警告的简单方法。

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.

暖风昔人 2024-09-02 14:28:15

这是逗号运算符 (,)

表达式 x 和 y 均被求值。整体表达式的结果是y,即后者的值。

很难说为什么在这里使用它。我想,出于演示目的。显然该函数可以重构为:

int foo()
{
  return 20;
}

This is the comma operator (,).

Both expressions x and y are evaluated. The result of the overall expression is y, i.e., the latter value.

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;
}
空宴 2024-09-02 14:28:15

此语法可用于保存 if- 语句的附加范围括号。例如,通常您会编写以下内容:

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

这可以替换为以下内容:

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

我认为这种编码风格的使用更多是出于摆姿势的冲动,而不是为了编写干净的代码。

This syntax can be used to save additional scope brackets of an if- statement. E.g. 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.

心凉 2024-09-02 14:28:15

这看起来是一个糟糕的代码示例。这可能是 C/C++ 中的有效语法,但我想不出您想要这样做的原因。

如果您想同时返回 x 和 y,在 C++ 中更好的方法是定义一个具有 x 和 y 属性的“Point”类或结构,然后返回它。另一种选择是通过引用传入 x 和 y,然后在方法中适当设置值。

如果该方法只返回 y,我只会“return y;”。如果需要在 return 语句之前“评估”x,则应在单独的行上完成。

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.

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. Another option would be to pass in x and y by reference, then set the values appropriately in the method.

If the method is going to just return y, I would just "return y;". If x needs to be "evaluated" before the return statement, it should be done on a separate line.

忱杏 2024-09-02 14:28:15

该 return 语句没有任何意义。

如果x被声明为易失性,它将强制访问(因为至少在C++中对易失性变量的引用被认为是外部可观察的行为) ,但事实并非如此。

如果存在某种具有副作用的计算而不是x,则它将执行该计算,然后返回y。然而,非易失性 x 没有副作用。该实现不需要执行任何没有副作用或外部可观察行为的代码。逗号运算符执行逗号左侧的所有内容,忽略结果,然后执行并保留右侧的值(除了在这种情况下可以随意忽略运算符的左侧)。

因此,return x, y; 语句与 return y; 完全相同。如果 x 不只是一个完全没有意义的执行对象,那么在风格上将其写为 x; 会更好。 return y;,这是完全相同的事情。这样就不会那么混乱了。

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.

If, instead of x, there was some sort of calculation with side effects, it would do that calculation and then return y. However, a non-volatile x has no side effects. 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; statement is the exact same thing as 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;, which is the precise same thing. It wouldn't be nearly as confusing that way.

┾廆蒐ゝ 2024-09-02 14:28:15

一方面,这可能是作者的无心错误。

另一方面,作者可能正在解释语法上正确的正确代码,而不是编译器警告。

无论哪种方式,返回多个结果的唯一方法是定义一个类并使用其实例,或者可能是一个数组或集合。

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.

不必你懂 2024-09-02 14:28:15

这是逗号运算符。这种语法可用于禁用编译器对未使用的变量x发出的警告。

This is the comma operator. Such syntax can be used to disable warning from compiler about unused variable x.

春花秋月 2024-09-02 14:28:15

在 for 循环之外,此命令运算符(与函数调用版本相对)的另一个主要用户是在执行某些操作后返回值的宏中。现在还有其他方法可以做到这一点,但我认为comman操作符曾经是最干净的方法。

#define next(A, x, y, M) ((x) = (++(y))%(M) , A[(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. These are other ways to do this now, but I think that the comman operator used to be the cleanest way.

#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.
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.

轮廓§ 2024-09-02 14:28:15

是否存在需要像这样创建 return 语句的情况?

IMO,我永远不会在像书中示例那样的函数中使用多个返回值。它违反了结构化设计。尽管如此,还是有很多程序员这样做!调试别人的代码时,我在每个 return 语句中为全局变量分配了一个值,这样我就可以找出执行的 return 。

Is there a case where a return statement would need to be created like this?

IMO, I would never use multiple returns in a function like the book example. 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.

失去的东西太少 2024-09-02 14:28: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;

}

I have seen this syntax used in C to do housekeeping when returning midway in an operation. 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;

}
萧瑟寒风 2024-09-02 14:28:15

本书试图消除那些在 C++ 之前学习过其他语言的人可能产生的困惑。在许多语言中,您可以使用类似的语法返回多个值。在 C++ 中,它将在没有警告的情况下进行编译(除非您指定 -Wall-Wunused-value),但如果您习惯了,它不会按照您期望的方式工作到其他语言。它只会返回最后一个值。

然而,作者似乎造成了比他阻止的更多的混乱,因为在 C++ 的 return 语句中使用这种语法没有可读的情况,除非像其他语言一样意外地使用它。他警告大多数人不会尝试的用法。但如果你这样做了,调试起来会非常混乱,因为多重赋值语句 int x, y = foo() 也可以很好地编译。

底线:始终使用 -Wall 并修复它向您发出的警告。 C++语法允许你写出很多没有意义的东西。

The book is trying to eliminate potential confusion of people who learned other languages before 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. 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. 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.

Bottom line: always use -Wall and fix what it warns you about. C++ syntax allows you to write many things that don't make sense.

薔薇婲 2024-09-02 14:28:15

当与 return 关键字一起使用时,逗号运算符返回 last 值,该值最初会令人困惑,但可以使事情更加简洁< /em>。

例如,以下程序将以状态代码 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

When used with the return keyword, the comma operator returns the last value, which is initially confusing but can make things more concise.

For example, the following program will exit with a status code of 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
旧伤慢歌 2024-09-02 14:28:15

如果 y 总是返回,那还有什么意义呢?

重点是 x 的副作用(即逗号运算符的左侧)。有关详细信息,请参阅 Justin Ethier 的回答。

是否存在需要像这样创建 return 语句的情况?

一个示例是 C++11 到 C++14 中的 constexpr 函数:此类函数可能不包含任意语句,但 恰好一个返回语句。

以下是 Patrice Roys 在 CppCon 上的“异常情况”的代码示例2016 年:

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

If y is always returned though, then what is the point?

The point is the side effect of x (ie of the left hand side of the comma operator). See e.g. Justin Ethier answer for details.

Is there a case where a return statement would need to be created like this?

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.

Here is a code sample from Patrice Roys “The Exception Situation" at CppCon 2016:

constexpr int integral_div(int num, int denom) {
    return assert(denom != 0), num / denom;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文