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

我已经用C和C ++进行了几年的编程,现在我正在学习一门大学课程,我们的书中有一个这样的function:

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

我从来没有见过这样的语法。 实际上,我从来没有见过在参数列表之外使用的操作符。 如果y总是回来,那么有什么意义呢? 有没有这样的情况下需要创build一个return语句?

(另外,我也标记了C,因为它适用于两者,虽然我的书特别是C ++)

逗号运算符主要用于像这样的语句:

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

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

根据C FAQ :

正确地说,一般expression式中逗号运算符的含义

e1,e2

是“评估子expression式e1,然后评估e2;expression式的值是e2的值”。 因此,e1最好包含一个赋值或者增量++或者减量 – 或者函数调用或者其他types的副作用,否则就会计算一个将被丢弃的值。

所以我同意你的观点,除了说明这是有效的句法, 没有其他意义。

如果你想用C或C ++返回两个值,你可以创build一个包含xy成员的结构,然后返回结构:

 struct point {int x; int y;}; 

然后,您可以定义一个types和帮助函数,以便您轻松地返回struct两个值:

 typedef struct point Point; Point point(int xx, int yy){ Point p; px = xx; py = yy; return p; } 

然后更改您的原始代码以使用帮助程序function:

 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", px, py); 

这个例子在C和C ++中编译。 虽然,正如马克build议下面,在C + +中,你可以定义一个构造函数的point结构,提供了一个更优雅的解决scheme。


在一个侧面说明中,直接返回多个值的能力在诸如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(px), y(py) {} Point operator, (int y_) const { Point p=*this; py = y_; return p; } }; Point get_the_point () { int x = 0; int y = 20; return (Point)x, y; } 

:p

就像所有在这里发表评论的人都认为这是毫无意义的,我不会不同意,只是看着这个例子,我会猜测这并没有多好:

作者得到了一个编译器的警告,提示函数中没有使用x,这是一个让警告消失的简单方法。

这是逗号运算符(,)

评估expression式x和y。 整体expression的结果是y,即后者的值。

这很难说为什么在这里使用。 我想,为了演示的目的。 显然,这个function可以被重构为:

 int foo() { return 20; } 

这看起来像是一个可怕的代码示例。 这在C / C ++中可能是有效的语法,但我想不出为什么你会这样做。

如果你想返回x和y,用C ++做的更好的方法是用x和y属性定义一个“Point”类或结构体,然后返回它。 另一个select是通过引用传入x和y,然后在方法中适当地设置值。

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

这个语法可以用来保存if语句的附加范围括号。 例如通常你会写下面的内容:

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

这可以由以下代替:

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

我认为这种编码风格的使用是由冒充的愿望,而不是写干净的代码。

这个回报声明没有意义。

如果x被声明为volatile ,它将强制访问(因为至less在C ++中引用volatilevariables被认为是外部可观察行为),但事实并非如此。

如果,而不是x ,有某种计算副作用,它会做这个计算,然后返回y 。 但是,非volatile x没有副作用。 执行不需要执行任何没有副作用或外部可观察行为的代码。 逗号运算符执行逗号左侧的任何内容,忽略结果,并执行并保留右侧的值(除了在这种情况下可以忽略运算符的左侧)。

因此, return x, y; 声明与return y;完全相同return y; 。 如果x不仅仅是一个完全没有意义的事情,那么把它写成x; return y;就更好了x; return y; x; return y; ,这是完全一样的东西。 这样就不会那么混乱。

一方面,作者可能是一个诚实的错误。

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

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

这是逗号运算符。 这样的语法可以用来禁止编译器关于未使用的variablesx警告。

在for循环之外,这个comman操作符的其他主要用户(与函数调用版本相关)是在macros中,在做了一些事情后返回一个值。 现在还有其他方法可以做到这一点,但我认为指挥官以前是最干净的。

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

请注意,这个macros是macros的一个不好的例子,因为它重复了x,可能是出于其他原因。 以这种方式使用逗号运算符应该是很less见的。 您书中的示例可能是为了使代码示例适合该示例的可用行数。

有没有这样的情况下需要创build一个return语句?

国际海事组织,我不会使用像本书的例子中的函数多个返回。 它违反了结构化devise。 不过,还有很多程序员呢! debugging别人的代码我已经在每个return语句中为全局variables赋值,所以我可以计算出执行的返回值。

我在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 ),但是如果习惯于其他语言,它将无法像您期望的那样工作。 它只会返回最后一个值。

然而,似乎作者引起了比他更多的困惑,因为在C ++的return语句中使用这样的语法是没有可读性的,除非意外地像使用另一种语言一样使用它。 他警告大多数人不会去尝试使用。 但是,如果你这样做了,那么debugging就会变得非常混乱,因为多重赋值语句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回答。

有没有这样的情况下需要创build一个return语句?

一个例子是C ++ 11中的一个constexpr函数,直到C ++ 14:这样一个函数可能不包含任意语句,而只是一个return语句。

以下是CppCon 2016上Patrice Roys“exception情况”的代码示例:

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