C++学期作业,看看有什么不妥的地方请指正谢谢

Paradin 2008-05-05 01:48:22
C++与Java
虽然Stroustrup 在一次访谈中说过语言的比较没有“意义”,大概他是从相应的应用领域的角度来解释的。但从语言的学习与理解来看,如果说C++比C高级在于允许用户自由抽象出类型与其模式,那么Java应当比C++的抽象程度更高能力更大,对于程序员来说屏蔽了一些不需要关心的细节,比如说取消指针,内存自动管理,用接口取代C++中引出问题的多重继承等等。这样的语言方便程序员集中注意力在问题空间解决方案和模式(类关系)的设计上,而将实现阶段中语言层次拖出的”泥水”减到最小,与C++相比也尽可能地降低了出现某些不明显错误的概率,因此很多时候可以大大提高开发效率,比较符合软件工程的思维,并且容易学习。而C++可能需要较长时间才能掌握,容易带进编码问题。
其次不像C++这种“大众”语言,Java像是一种“专有”语言,首先其语言标准被集中在几家大型企业之间争夺(IBM, Sun), 它的内置库中的类(如ClassLoader, String,甚至与网络有关的)是语言的一部分(很难想象只有Java语法我们可以做什么), 从语言层次上体现并强调了可重用性。而C++语言本身与第三方库是完全独立的(虽然有一个钦定的STL, 但可以用其他库实现相同功能如Boost或甚至自己重写)。原因是Java下面有强大的虚拟机支持,而面对网络和多线程等C++不得不面对平台相关性,不可能有整合进语言本身的那些方面的库,因而从这个角度讲C++比Java要纯。

学习C++的好处
前面说到与Java等高级语言相比C++更加接近底层,从本科生学习的角度来讲我们至少能够从一段C++代码跟踪到机器级别(RAM, 寄存器)上的行为, 因而能够了解编译器的实现和程序执行底层的明细, 比如CPU上代码组织和执行流程,寄存器的分配, 内存数据的位置和布局,这样便能比较深入地了解程序在机器级别上的运作过程,帮助理解和处理有时碰到的表面上看比较奇怪的问题。而这点Java等是做不到的,或者说很不方便,因而不适合这类学习,似乎更适合实时培训。此外C++本身也有高级语言的一般特性,因而可以作为理解其实现方式的一门学习性语言。但这些加起来也形成了C++混杂的特点,难怪有人只青睐Java也有人干脆抱着C不放。



STL库中关于函数对象(funtor)适配器的一个问题
接触了C++有一段时间了,可能还是理解得不够深入,仍然不能从语言的设计思维层次上提出一些稍抽象的有一定思辨意义的具“份量”的问题,针对一些高级特性也想象不到会带来哪些潜在的普遍问题。最近在了解STL, 发现了一个与其设计有关的具体一点的问题,虽然现实开发中很少会碰到,但从一方面反应了设计一个好的通用库的困难之处。

先介绍下问题的背景。
函数对象(Functor)类模板是STL库中实现的一些带一个参数或两个参数的类模板(一般在头文件functional中),比如less类是一个类模板, 成员函数bool less::operator()(const T& a, const T& b), 自然序下若a<b成立就返回true否则返回false. 之所以用函数对象取代函数指针一个原因是函数对象可以需要时被“适配”, 一种形式就是将其中一个参数和具体的某个值绑定,比如,适配函数bind2nd带两个参数,第一个参数是一个函数对象,第二个参数就是要被绑定的函数对象的第二个参数,例如 bind2nd(less, 10) 返回一个函数对象tmp, 该函数对象带一个参数x, 调用tmp(x) 等价于调用 less(x, 10). 并且该对象可以进一步被适配。

为了让函数指针也能被适配,stl提供了一个适配函数ptr_fun, 该函数带一个参数,类型为任何一函数指针,然后对其进行封装,返回与该函数指针相应的一个函数对象,这样就可以对该函数对象进行参数绑定了。举一个例子(VS2005和Mingw32下通过测试):

#include <iostream>
#include <functional> // for bind2nd and ptr_fun
using namespace std;

template <class T>
T Mul(T a, T b)
{
T result = a * b;
return result;
}

int main()
{
int result;
result = bind2nd(ptr_fun(&Mul<int>), 111)(10);
cout << result;
return 0;
}


首先&Mul<int>实例化出一个int 版本的模板函数Mul<int>, 然后作为一个函数指针被ptr_fun封装为一个函数对象, 使Mul的第二个参数为固定的111(也可绑定变量), 再用10进行调用, bind2nd(ptr_fun(&Mul<int>), 111)(10) 就等相当于调用 Mul(10, 111), 结果是1110.

Mul的参数是值传递, 很自然考虑到效率我们想将其改为常引用传递:
template <class T>
T Mul(const T& a, const T& b)
{
T result = a * b;
return result;
}
但是我尝试的所有编译器都会报错:”reference to reference is illegal”

为什么呢。我查看了STL库中关于这一块实现的源代码,其中bind2nd的返回类模板binder2nd的成员函数operator()如下:

result_type operator()(const argument_type& _Left) const {
// apply functor to operands
return (op(_Left, value));
}

result_type operator()(argument_type& _Left) const {
// apply functor to operands
return (op(_Left, value));d
}

其中op是被适配的函数对象, value是被绑定的参数值, 他们分别是bind2nd的第一个和第二个参数. 问题就出在argument_type&上,argument_type被typedef成最初原始函数指针的参数类型,即const int&, 那么argument_type& 就变成了 const int&&, 注意到语法上这是个引用的引用,但C++标准不支持这种形式,于是不论那个编译器都会报出类似“非法引用的引用”的错误。

那个这个问题如何解决呢?首先为什么它要擅自加上一个引用?这里又反应出了C++追求效率的一个特点,不论怎样argument_type可能是一个较大的对象, 那么先弄成引用再说。第二不要忘记参数绑定适配器主要是作用在现成的函数对象上的(而非通过ptr_fun从原始函数生成的函数对象), 例如less。 如果把类型定义全部交由程序员的话,那么可能他们会被逼写出类似less<const SomeClass&> 这样的实例化语句(其实只要写less<SomeClass>), 来完成本该由STL自动帮我们完成的事情,这样不方便也显得不那么高级。因此这个设计就不能面面俱到。

究竟能否解决上述问题呢。要么不用STL, 如果一定在STL环境下的话, 笔者的一个朋友提供了一个解决方法及实现,即在原始函数Mul<int>和ptr_fun之间再加一个适配层none_ref_ptr_fun,该适配器可以去除参数中的引用” &”使得形式上可以通过编译, 但实质上是在中间那一层新建了一个传值参数函数,执行时任然是值传递,原始的效率问题并没有解决。

其实提高效率不用引用用指针也可以,那么Mul就变成 T Mul(const T*, const T*), 这样就要求程序中显示传递地址了,函数体也要改。

关于整个问题的完整讨论参见本人博客上的一篇文章,地址是http://blog.csdn.net/Paradin/archive/2008/04/06/2254830.aspx。
...全文
271 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
Paradin 2008-06-09
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 elegant87 的回复:]
引用 18 楼 qinmingyan418 的回复:
引用 17 楼 kingwood2005 的回复:
引用 16 楼 Paradin 的回复:
引用 15 楼 SSSummering114 的回复:
引用 13 楼 Paradin 的回复:
引用 11 楼 Paradin 的回复:
引用 10 楼 hnbczmh 的回复:
引用 8 楼 liuworld 的回复:
引用 7 楼 Paradin 的回复:
引用 5 楼 calebgch 的回复:
引用 4 楼 Paradin 的回复:
引用 3 楼 zjw6861982 的回复:
引用 2 楼 qiucp 的回复:
引用 1 …
[/Quote]
elegant87 2008-06-01
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 qinmingyan418 的回复:]
引用 17 楼 kingwood2005 的回复:
引用 16 楼 Paradin 的回复:
引用 15 楼 SSSummering114 的回复:
引用 13 楼 Paradin 的回复:
引用 11 楼 Paradin 的回复:
引用 10 楼 hnbczmh 的回复:
引用 8 楼 liuworld 的回复:
引用 7 楼 Paradin 的回复:
引用 5 楼 calebgch 的回复:
引用 4 楼 Paradin 的回复:
引用 3 楼 zjw6861982 的回复:
引用 2 楼 qiucp 的回复:
引用 1 楼 babyvox1999 的回复: …

[/Quote]
Paradin 2008-05-25
  • 打赏
  • 举报
回复
/s
yanvenhom 2008-05-10
  • 打赏
  • 举报
回复
看不懂LZ在干嘛~~

老师叫你解释名次啊??

>_<
limingjiu 2008-05-10
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 Paradin 的回复:]
讨厌
[/Quote]

A girl?
limingjiu 2008-05-10
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 Paradin 的回复:]
讨厌
[/Quote]

A girl?
Paradin 2008-05-10
  • 打赏
  • 举报
回复
讨厌
Paradin 2008-05-09
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 SSSummering114 的回复:]
引用 13 楼 Paradin 的回复:
引用 11 楼 Paradin 的回复:
引用 10 楼 hnbczmh 的回复:
引用 8 楼 liuworld 的回复:
引用 7 楼 Paradin 的回复:
引用 5 楼 calebgch 的回复:
引用 4 楼 Paradin 的回复:
引用 3 楼 zjw6861982 的回复:
引用 2 楼 qiucp 的回复:
引用 1 楼 babyvox1999 的回复:
圣骑 - -!


前面和Java的比较及对这两个语言本质的理解没…
[/Quote]
zipodemo 2008-05-09
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 kingwood2005 的回复:]
引用 16 楼 Paradin 的回复:
引用 15 楼 SSSummering114 的回复:
引用 13 楼 Paradin 的回复:
引用 11 楼 Paradin 的回复:
引用 10 楼 hnbczmh 的回复:
引用 8 楼 liuworld 的回复:
引用 7 楼 Paradin 的回复:
引用 5 楼 calebgch 的回复:
引用 4 楼 Paradin 的回复:
引用 3 楼 zjw6861982 的回复:
引用 2 楼 qiucp 的回复:
引用 1 楼 babyvox1999 的回复: …
[/Quote]
qinmingyan418 2008-05-09
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 kingwood2005 的回复:]
引用 16 楼 Paradin 的回复:
引用 15 楼 SSSummering114 的回复:
引用 13 楼 Paradin 的回复:
引用 11 楼 Paradin 的回复:
引用 10 楼 hnbczmh 的回复:
引用 8 楼 liuworld 的回复:
引用 7 楼 Paradin 的回复:
引用 5 楼 calebgch 的回复:
引用 4 楼 Paradin 的回复:
引用 3 楼 zjw6861982 的回复:
引用 2 楼 qiucp 的回复:
引用 1 楼 babyvox1999 的回复: …
[/Quote]
kingwood2005 2008-05-09
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 Paradin 的回复:]
引用 15 楼 SSSummering114 的回复:
引用 13 楼 Paradin 的回复:
引用 11 楼 Paradin 的回复:
引用 10 楼 hnbczmh 的回复:
引用 8 楼 liuworld 的回复:
引用 7 楼 Paradin 的回复:
引用 5 楼 calebgch 的回复:
引用 4 楼 Paradin 的回复:
引用 3 楼 zjw6861982 的回复:
引用 2 楼 qiucp 的回复:
引用 1 楼 babyvox1999 的回复:
圣骑 - -!

[/Quote]
SSSummering114 2008-05-07
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 Paradin 的回复:]
引用 11 楼 Paradin 的回复:
引用 10 楼 hnbczmh 的回复:
引用 8 楼 liuworld 的回复:
引用 7 楼 Paradin 的回复:
引用 5 楼 calebgch 的回复:
引用 4 楼 Paradin 的回复:
引用 3 楼 zjw6861982 的回复:
引用 2 楼 qiucp 的回复:
引用 1 楼 babyvox1999 的回复:
圣骑 - -!


前面和Java的比较及对这两个语言本质的理解没有偏差么

[/Quote]
hslinux 2008-05-07
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 Paradin 的回复:]
引用 11 楼 Paradin 的回复:
引用 10 楼 hnbczmh 的回复:
引用 8 楼 liuworld 的回复:
引用 7 楼 Paradin 的回复:
引用 5 楼 calebgch 的回复:
引用 4 楼 Paradin 的回复:
引用 3 楼 zjw6861982 的回复:
引用 2 楼 qiucp 的回复:
引用 1 楼 babyvox1999 的回复:
圣骑 - -!


前面和Java的比较及对这两个语言本质的理解没有偏差么


[/Quote]
Paradin 2008-05-07
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 Paradin 的回复:]
引用 10 楼 hnbczmh 的回复:
引用 8 楼 liuworld 的回复:
引用 7 楼 Paradin 的回复:
引用 5 楼 calebgch 的回复:
引用 4 楼 Paradin 的回复:
引用 3 楼 zjw6861982 的回复:
引用 2 楼 qiucp 的回复:
引用 1 楼 babyvox1999 的回复:
圣骑 - -!


前面和Java的比较及对这两个语言本质的理解没有偏差么

[/Quote]
donwmufromdying 2008-05-06
  • 打赏
  • 举报
回复
I'm necromancer
Paradin 2008-05-06
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 hnbczmh 的回复:]
引用 8 楼 liuworld 的回复:
引用 7 楼 Paradin 的回复:
引用 5 楼 calebgch 的回复:
引用 4 楼 Paradin 的回复:
引用 3 楼 zjw6861982 的回复:
引用 2 楼 qiucp 的回复:
引用 1 楼 babyvox1999 的回复:
圣骑 - -!


前面和Java的比较及对这两个语言本质的理解没有偏差么
[/Quote]

hnbczmh 2008-05-06
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 liuworld 的回复:]
引用 7 楼 Paradin 的回复:
引用 5 楼 calebgch 的回复:
引用 4 楼 Paradin 的回复:
引用 3 楼 zjw6861982 的回复:
引用 2 楼 qiucp 的回复:
引用 1 楼 babyvox1999 的回复:
圣骑 - -!


前面和Java的比较及对这两个语言本质的理解没有偏差么
[/Quote]
cryingzgz 2008-05-06
  • 打赏
  • 举报
回复
-_-!
liuworld 2008-05-06
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 Paradin 的回复:]
引用 5 楼 calebgch 的回复:
引用 4 楼 Paradin 的回复:
引用 3 楼 zjw6861982 的回复:
引用 2 楼 qiucp 的回复:
引用 1 楼 babyvox1999 的回复:
圣骑 - -!


前面和Java的比较及对这两个语言本质的理解没有偏差么
[/Quote]
Paradin 2008-05-06
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 calebgch 的回复:]
引用 4 楼 Paradin 的回复:
引用 3 楼 zjw6861982 的回复:
引用 2 楼 qiucp 的回复:
引用 1 楼 babyvox1999 的回复:
圣骑 - -!
[/Quote]

前面和Java的比较及对这两个语言本质的理解没有偏差么
加载更多回复(6)

64,648

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧