返回值的C++中

 我来答
潮悌UA
2016-05-18 · TA获得超过100个赞
知道答主
回答量:191
采纳率:0%
帮助的人:161万
展开全部

函数可以有返回值,也可以没有返回值。对于没有返回值的函数,功能只是完成一个操作,应将返回值类型定义为void,函数体内可以没有return语句,当需要在程序指定位置退出时,可以在该处放置一个
例: void backward(int n){cout<<n%10;if(n<10)return;else backward(n/10);}int main(){int n;cout<<输入整数:<<endl;cin>>n;cout<<原整数:<<n<<endl<<反向数:;backward(n);cout<<endl;return 0;}函数可以有返回值,只要 return 就可以给出一个。不过我们常常不用它--有两个原因:
1、C/C++里返回值是复制出去的,而对于大的对象,复制的代价很高;
2、有些对象是不能复制的--至少编译器不知道怎么复制--比如数组。
于是我们有了很多这样的函数:
bool GetObj(ObjType& obj);
bool Encode(const char* src, char* dest);
用一个参数来代替返回值,而返回值只是指示函数执行是否成功。我本人一直固执的认为,这是C的处理方式,C++不该这样,返回就是返回,就该光明正大的返回,而不是在文档里为某个参数悄悄的注上: // out
诚然返回一个大对象是困难的,但这个困难是 C 程序员的,而不是 C++ 程序员的 -- 我们可以返回指针。C也有指针,但很少有人敢在 C 函数里返回一个指针,因为:
1、如果指针指向栈变量,毫无疑问,要么你不用这个返回值,要么是一个错误;
2、如果指针指向堆变量,要么你在祈祷用这个函数的程序员会好好的看文档且足够细心会调用 free,要么就是内存泄漏;
3、如果指针指向 static 变量,那么用这个函数的程序员牢牢记住“下次调用这个函数以后,上次的返回值也会跟着变”,要么就是你被别人骂成“专出 BUG 的垃圾”。
在C++里直接返回裸指针的话,情况并不会有什么起色,不过 C++ 有智能指针的,通常它们指向堆变量,占用的空间和裸指针一样大。考虑前面第一个函数,我们写成:
std::auto_ptr<ObjType> GetObj();
那么一切迎刃而解,返回值如果你不要,作为临时变量,会立即被析构,返回的对象被释放;如果你要,就得赋值给另一个智能指针。总之不用程序员记得,编译器会保证这个对象的释放。
考虑第二个函数,稍微有一点麻烦,因为 auto_ptr 是不能用来持有数组的,不过,在C++的世界里,std::string 几乎总是比 char* 好用:
std::auto_ptr<std::string> Encode(const char* src);
最后考虑最麻烦的情况:
bool AssembleObjList(ObjType objList[], size_t length);
这种类型的函数无论是在 C标准库里,还是在各种操作系统的 API 里,比比皆是,事实上它存在两大缺陷:
1、如果需要的数量超出给出的,要么是一个安全问题(经典的缓冲区溢出,如 strcpy),要么是失败,程序员不得不作出估计--众所周知,程序员的估计能力比他们的薪水低得多;
2、如果执行成功,到底 Assemble 了多少个?
于是我们见到了这样的函数:
bool AssembleObjList(ObjType objLIst[], size_t* lengthPtr);
这个函数通常是两步调用的:
size_t length = 0;
AssembleObjList(0, &length);
ObjType* objList = new ObjType[length];
AssembleObjList(objList, &length);
for(size_t i=0; i<length; ++i)// 处理每个元素
这种形式能解决上面列出的两个问题,但这实在是太麻烦、太可恶了。我的答案仍然是--C++程序员应该用C++的库:
std::auto_ptr<std::vector<ObjType> > AssembleObjList();
又干净,又舒服!
C++标准库里居然没有一个可以持有数组的智能指针,所以 boost库不错,可以这样:
std::pair<boost::scoped_array<ObjType>, size_t> AssembleObjList();
可惜这个并不比标准库的解法更优秀--因为要返回数目的缘故,不过我个人更喜欢这个解,因为他更接近最优的解--传说中的 trule 手法:
TruleVector<ObjType> AssembleObjList();
其中 TruleVector是这样一个模板:它只有两种操作,一是构造,二是自动转型为 std::vector,而且它具有 “auto_ptr 式的所有权转移语义”。也就是说,TruleVector除了作为数组型的返回值,你无法把他用于其它任何任务。
不过由于 std::vector具有值语义,所以写的代码还是稍微有一点不同寻常:
typedef std::vector<ObjType> ObjListType;
ObjListType list;
list.swap(AssembleObjList());
最后一句在有的产品上可能要写成:
list.swap(static_cast<ObjListType>(AssembleObjList()));
这样别扭的原因,可以归咎于C++库里缺一个引用语义的线性容器。

已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式