我已经学习了几年的C和C++编程,现在正在参加大学课程学习,我们的教材提供了一个函数示例:
int foo(){
int x=0;
int y=20;
return x,y; //y is always returned
}
我从未见过这样的语法。事实上,我从未见过除了参数列表之外使用,
运算符。如果y
总是被返回,那么这有什么意义呢?是否存在需要创建这样的返回语句的情况?
(另外,我也标记了C,因为它适用于两种语言,尽管我的书特别讲解的是C++)
我已经学习了几年的C和C++编程,现在正在参加大学课程学习,我们的教材提供了一个函数示例:
int foo(){
int x=0;
int y=20;
return x,y; //y is always returned
}
我从未见过这样的语法。事实上,我从未见过除了参数列表之外使用,
运算符。如果y
总是被返回,那么这有什么意义呢?是否存在需要创建这样的返回语句的情况?
(另外,我也标记了C,因为它适用于两种语言,尽管我的书特别讲解的是C++)
e1 , e2
中,逗号操作符的含义可以精确地表述为:“评估子表达式e1,然后评估e2;表达式的值是e2的值。” 因此,e1 最好涉及赋值、自增++、自减--、函数调用或其他某种副作用,否则它将计算一个会被丢弃的值。
所以我同意你的看法,除了证明这是有效的语法之外没有其他意义。
如果你想在 C 或 C++ 中返回两个值,你可以创建一个包含 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++中编译通过。尽管如Mark所建议的,在C++中你可以为point
结构定义一个构造函数,这可以提供一种更优雅的解决方案。
顺便说一下,在支持直接返回多个值的语言(如Python)中,这种能力非常棒:
def foo():
x = 0
y = 20
return x,y # Returns a tuple containing both x and y
>>> foo()
(0, 20)
point
结构体需要一个接受两个 int
参数的构造函数。 - Mark Ransomstruct
只是一个例子 - 话说,你能详细说明一下吗?严格来说,在 C 中没有构造函数。不过,无论如何,这段代码在 C 和 C++ 中都可以编译通过,并且 x
和 y
成员可以直接被代码访问。 - Justin Ethierreturn point(x,y);
。抱歉我说话有点神秘。 - Mark Ransom在参数列表中的逗号只是用来分隔参数,不同于逗号操作符。像你例子中的逗号操作符会评估 x 和 y 两个值,然后丢弃 x。
在这种情况下,我猜想这是某人试图返回两个值时犯的错误,并且不知道该怎么做。
逗号运算符主要用于像这样的for
语句中:
for( int i=0, j=10; i<10; i++, j++ )
{
a[i] = b[j];
}
第一个逗号不是逗号运算符,它是声明语法的一部分。第二个是逗号运算符。
i
和 j
。还有其他一些情况,如果您想强调两个语句非常紧密地联系在一起,不应拆分,那么可能会使用逗号而不是分号。例如:std::memcpy(data, moredata, moresize), datasize+=size;
。我喜欢将这些语句放在一起,以避免有人意外移动或删除第二部分。 - André Caron这并没有真正回答原始问题,但可能对一些人很有趣。如果你想在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);
pair
。当然,这并不能直接推广到超过两个值的情况。 - David Thornley 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没有被使用,而这是消除警告的简单方法。
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++中定义一个"Point"类或结构体,其中包含x和y属性,然后返回该类或结构体。另一种选择是通过引用传递x和y,然后在方法中适当地设置值。
如果该方法只返回y,则只需使用"return y;"。如果在返回语句之前需要"计算" x,应该在单独的一行上完成。
这个return语句没有任何意义。
如果x
被声明为volatile
,它会强制访问(因为至少在C++中,对volatile
变量的引用被认为是外部可观察行为),但它并没有被声明为volatile
。
如果不是x
,而是一些具有副作用的计算,它将执行该计算,然后返回y
。然而,非volatile
的x
没有副作用。实现不需要执行任何没有副作用或外部可观察行为的代码。逗号运算符执行逗号左侧的任何内容,忽略结果,并执行和保留右侧的值(除了在这种情况下可以忽略操作符左侧)。
因此,return x, y;
语句与return y;
完全相同。如果x
不是完全没有意义的东西,那么以x; return y;
的方式编写会更好,这是完全相同的。这样做不会让人感到混乱。
x
替换为具有副作用的某个表达式,也没有必要像那样将其塞入返回语句中。只需将其作为单独的语句:expr_with_side_effects; return y;
。 - Keith Thompson