C++为什么不支持元组作为函数返回值
用C++写程序的时候,最郁闷的就是我想要返回两个值,必须构造一个结构体来返回,或者一个通过返回值,另外一个通过引用传递参数。而其他语言比如python, erlang却支持。
在stack overflow也看到了这个问题 http:///questions/321068/returning-multiple-values-from-a-c-function
-
-
马瑜
4 票
-
![马瑜](http://image68.360doc.com/DownloadImg/2014/01/0520/38037936_3.jpg) - 6090
-
有二种方法可以解决
- 通过std::pair<one, two>来解决
- 更灵活的方式可以通过boost::Tuple
-
1
pair只能就解决两个返回值的问题。
boost::Tuple,还要包含boost,并且还要构造对象和我自己声明一个结构体差不多。
我原本的意思是能否从更深层次解释下,为什么可以非常简明的写法,一定要绕这么多弯。
– 黄新颖
2011-10-21
-
0
Note: C++11 已经开始支持tuple了
– tlh1987
2012-10-20
-
0
@黄新颖 重点在于tuple是Python的内嵌类型,支持多长度的,所以可以直接作为多返回值使用;而C++没有最初内嵌的相应类型,所以需要通过库的拓展来实现。
即便是C++11也是如此。
– KPSN_Leo
2013-01-01
这个问题好大,python我不太懂还是从C++方面来说吧 C++最早引入对象模型的时候,语言的设计专家们已经在此基础上做了很多优化,但局部的编译生成的代码,也因为封装牺牲了空间和时间,设计者和编译器的构建人员为了C++的高效性,尽量减少语言在因为引入封装而带来的成本,最早的Stroustrup设计的简单对象模型发展到现在已经做了很多的优化,C++定义了对象的语法,但没有引入特定的对象作为语法的部分,我想还是考虑到效率的原因,函数的返回值在函数语义学上,构造一个返回语法支持的对象的函数,和一个返回值的函数,估计整个语法编译器都要重新设计。 每种语言都有自己的特长,应该是越高级的语言使用越方便,但因为方便而带来的是空间和时间的成本。
-
0
构造一个返回语法支持的对象的函数,和一个返回值的函数,估计整个语法编译器都要重新设计。
倒不会严重到这个程度,哈哈。语言本来就是越贴近使用者越好,就像C#原先不支持缺省参数一样,后来又在新版本中加入了缺省参数的支持。
– 黄新颖
2011-10-21
-
0
这个和C/C++设计年代所需解决的问题有关系,也和c++不是纯面向对象,依赖简单的数据类似有关。
– 吴绩伟
2011-10-21
-
0
如果说为了效率而不增加多个返回值,那C++中的异常是个例证。 C++为了对异常的支持,性能和编译出来的代码都有不小的开销,我现在还一直认为异常是C++的一个败笔。
– 黄新颖
2011-10-21
-
0
@黄新颖 异常对于OOP来说是很重要的。不过C++的异常的确比较鸡肋,大家都适应C的用法了
– 灵剑2012
2012-09-14
1.想像中C语言如何支持函数有可变数量返回值 目前的编译器不支持,但是要给编译器加一种call的方式,让这种call支持返回多个返回值也是有可能的 比如我们增加一种 _ _klcall,这种函数把返回个数放在堆栈 - 0xc处,再之后是第一个返回值,之后是第二个。。。 这样的c语言代码
- _ _klcall int,int addsub(int a,int b)
- {
- return (a + b),(a -b)
- }
- int i,j = addsub(5,6);i == 11,j == -1
假设新的编译器支持这种 _ _klcall产生的汇编代码
- ;;函数
- ;;__klcall int,int addsub(int a,int b)
- ;;{
- ;; return (a + b),(a -b)
- ;;}
- ;汇编代码
- push ebp
- mov ebp,esp
- push ebx
- mov eax,dword ptr ss:[ebp+0x8];参数1
- add eax,dword ptr ss:[ebp+0xC];参数1 + 参数2
- mov ebx,eax
- mov eax,dword ptr ss:[ebp+0x8];参数1
- add eax,dword ptr ss:[ebp+0xC];参数1 - 参数2
- ;add结果在ebx sub结果在eax
- ;现在开始输出。从 [ebp - 0x4]开始.因为[ebp]里保存的是调用前的ebp不能破坏
- mov dword ptr[ebp - 0x4], 2;先输出共返回两个参数
- mov dword ptr[ebp - 0x8], ebx;再输出返回add结果
- mov dword ptr[ebp - 0xc],eax;再输出返回sub结果
- pop ebx
- pop ebp
- retn 8
- ;;调用
- ;;int i,j = addsub(5,6);i == 11,j == -1
- ;;汇编代码
- push 0x5
- push 0x6
- call funAddSubAddres
- ;;这时esp指向0x5; [esp - 4]是上一个调用call的下一个地址,[esp - 8]是保留的ebp值,就是上面说不能破坏那个
- mov eax,[esp - 0xc]//上个调用共返回多少个函数
- mov [ebp - 0x4], [esp - 0x10]//add的结果 == 11
- mov [ebp - 0x8], [esp - 0x14]//sub的结果 == -1
- ;这时堆栈应该是这样的
- ; 0012FDD8 ffffffff;sub的结果-1
- ; 0012FDDC 0000000b;add的结果11
- ; 0012FDE0 00000002;返回两个返回值
- ; 0012FDE4 /0012FF08; 调用时的ebp
- ; 0012FDE8 |00411556; 返回到 call funAddSubAddres 的下一语句
- ;esp 指向这里->0012FDEC |00000005;
- ; 0012FDF0 |00000006
2.从以上假想代码来看,要让函数支持多个返回值,也很简单,效率我也看不出有多大问题。如果把返回个数放在eax里返回,代码还可以再少一些。 3.所以我觉得之所以现代c函数不支持多个返回值,是因为编译器厂商没觉得有那必要。 如果想要这种 local a,b = subadd(5,6)这种这么方面的特性,那直接用脚本好了比如lua,python. 4.现在做游戏,特别是客户端游戏,如果不用脚本直接用c++,会让很多人把嘴张得大大的:怎么可能?其实还是淫者见淫
-
0
这个是有问题的,而且问题很严重。esp以上的部分绝对不可以存储数据。因为这时候如果有个中断进入的话,会立即覆盖掉esp以上的数据,这样运行结果就会出错。
– 灵剑2012
2012-09-14
-
0
local a,b = func();这种方式如果只是为了赋值的话,感觉类似语法糖,只是一个便捷的操作而已。。。
– 刘江
2012-10-10
主要还是没有设计这个编译器功能吧, {min,max} = find_min_max(...) 相同的功能完全可以写成 void find_min_max(..., &min, &max); 或者用引用 void find_min_max(..., min, max); 没有必要为这种情况定义一种语法,只会导致混乱。
-
0
丝毫没有见到过Python或者Lua中因为引入多重返回值而变得混乱。
– KPSN_Leo
2013-01-01
-
0
@KPSN_Leo 基本语法的设计就不一样,Python大约也不能把程序全写在一行上吧。
– 灵剑2012
2013-01-04
终于想明白为什么C/C++只能返回一个值,而其他的脚本语言可以返回多个值了。c++在编译成汇编语言中,约定返回值用eax保存,并且只能保存一个值,除非改汇编指令。
- int add(int a, int b)
- {
- return a + b;
- }
-
- int process()
- {
- int value = 0;
- __asm
- {
- push eax
- push 2
- push 3
- call add
- add esp, 8
- mov value, eax
- pop eax
- }
- return 1;
- }
-
0
不不,你试试返回一个结构体,这个结构体会存在堆栈里面。这也是调用约定的一部分。
– 灵剑2012
2012-09-14
我觉得从汇编角度讨论这个问题可能不太好,这和C++语言是一种强类型语言有关。 在Python中,它是一种弱类型语言,一个元组中存放的可以是任何类型;而在C++中和元组最相近的vector中的元素必须是同一类型。 如果返回值是多个同类型值,比如是2个int数,那么C++可以用vector返回;但是如果是不同类型就不行了。 每个语言都有自己的长处,要善于选择使用语言。
我以前看python的书说 python 中的元组 貌似是防止 错误修改 才搞的 c++ 里边可以定义 不可修改的 结构或者类型
-
1
我想用元组的目的不是说想把他变成不可修改,我比较好奇为什么C++不能让我写一个这样的函数。
-------------------------------------------
int min, max;
min, max = find_min_max( const list& l );
-------------------------------------------
int err_no;
string err_msg;
errno, err_msg = last_error();
– 黄新颖
2011-10-21
-
0
用stl中的map啊
– Thomas
2011-10-21
C++是通过把返回值放置在EAX里面来获取返回值的,所以只能存放一个值(包括指针等等)
pair很好 如果要返回多个参数boost里有很多方案可用
-
1
题目是Why ,而不是How
– 黄新颖
2011-10-21
-
0
我的理解是C++就是通过那些模板结构体类型支持了元组返回值。
只是他的返回值要定义的,不像动态语言那样。
没准哪年c++新标准,就加上 return xxx,xxx
– 孙继峥
2011-10-21
你的意思是语法上想这么写:
这的确是一种语法上的便利性。实际上函数中最终有一个return,返回一个元组“对象”。它不是数组这种简单的“同一的多个对象”,所以这个对象能存放多种类型的对象,那么C++就必须为没个对象内置"运行期识别"的类型识别,包括内置对象,你觉得可能吗。这是一个高级对象,C++语言设计目的之一就是只引入基本的内置类型,用户需要的高级类型需要自己构造。
|