简单地说,为什么下面的代码会编译?
#include<iostream>
int foo(){
return 0,1;
}
int main(){
int a,b = foo();
std::cout << a << " " << b << std::endl;
std::cout << foo();
return 0;
}
我正在使用64位Window的机器,并使用Dev-C ++进行编译(使用MinGW GCC 4.5.2 32位编译器)。
此代码打印以下输出:
2686824 1
1
我强烈怀疑a
中包含的值是存储在未初始化变量中的常见垃圾。
从this question可以清楚地看出,从函数中返回多个值并不是行业中常见的做法,在学术机构教授的编程课程中肯定会受到劝阻和惩罚。
那么为什么它会起作用?由于我已经成熟为程序员,我已经意识到编译器错误的难以置信的价值,它比链接器或运行时错误更容易理解,并且显然比错误更好。
要明确的是,我更感兴趣的是为什么从语言设计的角度来看这是允许的,而不是编译器如何做其事情的技术细节(除非,在这种情况下,实现现实或技术后果已经做出很难/不可能检测/管理多个return
变量。)
是否有一些深奥的案例认为多变量return
声明有用?
答案 0 :(得分:16)
您仍然只返回一个值1
。
return 0,1;
使用comma operator,其结果是右手边。使用正确的警告级别,您的编译器(至少gcc和clang)将发出警告,因为它的左侧没有效果。
如果您确实想要返回多个值,则可以返回std::tuple
(或std::pair
):
auto fun () {
return std::make_tuple(0,1);
}
int main () {
int a, b;
std::tie(a,b) = fun();
// Now a == 0, b == 1
}
C ++ 17中的等效替代:
auto fun () {
return std::make_tuple(0,1);
}
int main () {
auto [a,b] = fun();
}
答案 1 :(得分:4)
0,1
是一个除了按顺序计算两个表达式并且得到第二个运算符(1)的值之外什么都不做的运算符。因此,return 0,1
相当于说return 1
。
int a,b = foo();
创建了两个变量。 a
未初始化,b
的返回值为foo()
。
这就是为什么b
的值为1而a
的值是古怪的(未定义)。
IME,逗号运算符的主要好处是C中的for
循环。例如,假设您想要枚举链表的元素。列表没有内置的订单概念,因此您最终会在列表中保留两个位置跟踪器。
for (index = 0, curr_node = list_begin;
curr_node != NULL;
++index, curr_node = curr_node->next)
{
// Stuff
}
这对于可读性来说是一个方便的小技巧,它还保证index / curr_node无论你使用break
还是continue
做什么都保持同步。