为什么说C++落伍了?

前一段时间,在C++版的几个帖子里参与了一点讨论。也许某些观点触痛了几个C++爱好者的神经,被指责为“不懂装懂”、“没有建设性”、“踢场子”。
我当然不是大师,也不是牛人,不过相比某些满嘴跑火车,夸夸其谈没有来路的“OO规则”、什么“黑盒OO”、“白盒OO”的“神人”(比大师还牛,一开口就能“自主创新”),自信还是要懂那么一点点。
既然有人要我“拿出证据”,我也必须对自己的言论负责,就再装一回懂,谈谈“为什么C++落伍了”。
我的意思当然是讨论了,不过某些人非要说我“踢场子”,就当是踢场子吧。

先说一点,我并没有贬低C++,C++有很多优点,诸如语言能力比较强,实现平台多,有很多免费的工具和库可用等等,我在另一个帖子里也说了“C++是3GL的集大成者”。我针对的只是“C++就是好,就是好来就是好”、“全面优于其他语言”、“综合能力优于其他语言”(这种观点还算可以讨论)。

C++的一些缺点,诸如学习曲线的问题,缺少标准的应用框架(GUI、线程库、GC)等等,已经说得太多了,连BS这样的“C++之父”都说了(当然他是有一些辩解的)。
我就象某人那样“只谈技术”、“只谈语言本身”。

1. C++对象模型问题
准确地讲,是C++的对象存储模型。
C++的对象存储,使用一种简单模型,也就是对象(对象是类的实例)直接代表一个存储区域,存储它的内部成员。这种结构当然有它的优点:占用存储空间比较少,对象的创建和销毁比较简单也比较快(针对基于栈的,基于堆的对象在C++中要显式使用一个指向对象的指针,更加复杂)。
// 这些特征让我们想起它产生的时代背景:计算机比较慢、内存比较少。
但是这种结构也有明显的问题:
a. 为了实现多态,需要引入指针或引用。
b. 子类兼容也需要引入指针或引用。
c. 默认是基于栈的,而对象占用的空间较多(相比简单类型),潜在的导致栈溢出的可能性更大一些。
d. 对象的赋值是拷贝,这经常导致代码的性能问题(要解决就要显式使用指针)。
e. 这种存储结构有被利用进行缓冲区溢出攻击的潜在可能。

前面几个都是常识了,讲解C++的书多少都会提及,只多说一下e问题。
由于C++的对象直接映射到一个实际存储空间,利用缓冲区溢出篡改对象的内部数据结构从而改变程序流程的可能性要比使用引用模型的语言大。
比如如下程序:

#include <iostream>
#include <string.h>

using namespace std;

class bot
{
private:
char password[8];
public:
bot(){strcpy(password, "abc");};
virtual ~bot(){};
bool checkpwd(const char *pwd){return (!strcmp(password, pwd));};
};

char s[8];
bot b;

int main()
{
for(;;)
{
cout << "Enter password: ";
cin >> s;

if (b.checkpwd(s))
{
cout << "Access permitted.\n\n";
break;
}
else
cout << "Access denied.\n\n";
}
return 0;
}

密码是abc,正常情况下不输入abc是不可能通过的。
但是我们输入123456789012123试试,还是不行。
我们再输入123,居然通过了。
原因就是我们输入123456789012123的时候造成了缓冲区溢出,把b的内部数据password覆盖了,改成了123,这样再次输入123的时候就通过了。
(注:
(1). bcc32 5.82(BCB 2006)和cl 13.10.3077(VC++ 7.1)编译通过,其他编译器未测试。
(2). 之所以需要12个字节才覆盖到b是数据对齐的原因。
(3). 这个例子只是用来说明C++的对象模型可能导致缓冲区溢出攻击的原因,凡是批评程序结构不当、风格有问题的免开尊口。


这个例子是基于静态数据区的。基于栈分配,仍然可能构成攻击条件,尽管某些编译器(比如VC++ 7.1),在编译时有意调整局部变量的顺序,把char[]之类的缓冲区排在高地址而避免潜在的风险。但是这种避免只是在一个函数内部,不同函数中的局部变量编译器就无法调整了,所以一个函数内部的缓冲区还是可能溢出到直接或者间接调用它的函数在栈上创建的对象(当然形成攻击要更困难一些,因为覆盖了函数的返回地址)。

在基于引用的对象模型中,声明一个对象只是创建一个引用(本质上是指针),对象的实际存储空间是在堆上动态创建的,形成这种缓冲区溢出攻击的条件要困难得多。而在栈上的这种缓冲区溢出攻击,对基于引用的对象模型彻底无效,因为你再溢出也只能在栈段内部,无法篡改堆上的对象存储空间。

客观地说,C++的对象模型是80年代的产物(1989年的Turbo Pascal 5.5就使用与C++类似的对象模型,Delphi中仍然兼容支持这种object类型,但是标明“不推荐使用”)。
它无法隐藏指针和引用,在语法上不完美,在结构上有严重问题(允许在OO结构中暴露指针,这已经破坏了OO的三大特征之一---封装),而且容易被利用进行缓冲区溢出攻击。
90年代以来的OOPL,毫无例外地都使用引用模型,没有使用类似C++的模型的(也许我孤陋寡闻了,但至少象C#、Delphi、Java这些使用比较广泛的语言都是如此)。
这只能证明C++的对象模型过时了,总不可能C++的设计者最高明,其他语言的设计者都很蠢吧(可能性有多大呢?应该比你买彩票中大奖的可能性要小)。
而一个基本对象模型都过时了的语言,称之为“落伍”不算夸张吧。:)

(待续,明天接着写,没时间就是后天)
...全文
10036 383 打赏 收藏 转发到动态 举报
写回复
用AI写文章
383 条回复
切换为时间正序
请发表友善的回复…
发表回复
Tishion 2012-09-06
  • 打赏
  • 举报
回复
挖一个坟
/偷笑
xj_20110101 2011-05-17
  • 打赏
  • 举报
回复 1
楼主的帖子,我没有看完。
但是,这并不能妨碍我BS楼主。
我只要一看到“落伍”俩字,我就情不自禁的要BS你,楼主。
你别说,C++里的什么功能,会造成什么问题;也别说,C++在某方面不如某某某;你更别说C++性能等等。
所有这些问题,都是像你这类使用C++的人的问题,而不是语言本身的问题。
。。。
TimothyField 2011-03-10
  • 打赏
  • 举报
回复 1
我有时做点木工,有了电动螺丝刀,但有时候还用传统的螺丝刀。
C++不过是个工具,不同工具有不同的用途,只有合用不合用,哪有落伍不落伍的——当然边缘化是可能的,毕竟替代选项多了。

高性能计算,C++跟ASM组合就比较好。
  • 打赏
  • 举报
回复 1
说这话不是找死吗
若非零落 2010-03-23
  • 打赏
  • 举报
回复
mark
liang118038liang 2009-12-06
  • 打赏
  • 举报
回复 2
楼主真的不是一般的落伍,放着好好的string不用却用数组。如果用数组又不是这么用吧,回去好好看看数据结构,都不会出这样的代码出来啦,连个链表还不会写??
axx1611 2009-12-05
  • 打赏
  • 举报
回复
楼主您知道什么是OO么,从您的代码中真没看出来
牧羊帮 2009-11-30
  • 打赏
  • 举报
回复 1
不好好写码在这整这些没用的
q313170768 2009-10-13
  • 打赏
  • 举报
回复
语言这东西不能用落伍来形用吧?
yaya__ 2009-10-10
  • 打赏
  • 举报
回复
不会吧!我还在学呢!
luxiao_crazy 2009-08-25
  • 打赏
  • 举报
回复
我感觉C#更稳定,我喜欢
ken8163 2008-11-29
  • 打赏
  • 举报
回复
终于看完,你们辛苦了!
再加一句,睡觉
mianer11 2008-11-25
  • 打赏
  • 举报
回复
那应该学什么呢??
Kittyloveu 2008-10-14
  • 打赏
  • 举报
回复
这个帖子害我看了几个小时,以后再也不这样看帖子了,我今天上午还要上课呢,以后再也不这样看帖子了,日,看来CSDN还是坚持要少来,以后不看这样的帖子了,打乱了我很久以来的作息计划,再不来CSDN这样看帖子了,去英文网站吧
Kittyloveu 2008-10-14
  • 打赏
  • 举报
回复
补充一下,我只是一个普通学校的临近毕业的大四学生,学计算机的,想搞软件开发,不是谁的马甲,这就是我目前为止唯一的csdn号,常来csdn看看可是发现一般也学不到什么东西所以也不怎么想来了,以后还是多去写英文网站吧,好在自己的英文不算太菜,专业英语又很简单.
Kittyloveu 2008-10-14
  • 打赏
  • 举报
回复
我看完这个帖子,感想很多,想法也很多,首先就是:学习了!

第二,我感觉楼主说的单纯的Cpp模型有点落后,但不影响它的使用什么的,这段话是对的;

第三,这个帖子我决定看完,可是,当我终于看完的时候我发现我已经看了2个多小时,说实话,长这么大还没有花过这么长时间来看过一个帖子的,汗;

第四,对一个网友的话很赞,很顶它,喜欢DelphiGuy看到后能够有所想法;可惜DelphiGuy可能不会再看这个帖子了,遗憾的是这个哈姆雷特说的话很有道理为什么没有人重复

与其在这卖弄你的知识,不如告诉告诉新人们,你的学习里程,你的心得。哪个阶段适合学什么,你是怎么走过来的等等……我认为象你这水平的人物,应该都是心如止水了啊,“万物皆对象”,多象出家人的境界呀~~~~~

你就是再NB,从2楼起的所有人也顶多是说声:“我在CSDN看到过一个家伙,那B的水平真的NB”

你何不让我们今后都说:“真亏了当初在CSDN上认识了一个叫DelphiGuy的大哥,我今天才这么NB!!!”
//*********************************************************************************//

DelphiGuy可以说下这方面的内容啊,

最后,说点自己个人的东西,我是先学习的C,后来看了Cpp,最后才接触的Delphi,但是我很喜欢Delphi,可惜Delphi前途黯淡,Borland把他卖给易博龙了现在,不过还是希望Delphi可以强强起来,另外我也不讨厌Cpp;
还有好多感想,现在也写不出来了,我平常都是0点睡觉的,今晚下载点东西,顺便看下帖子,可是没有想到会看到一个这么长这么个性的帖子,还有,中间DelphiGuy骂一个人,那样似乎不太好,为了一门语言的一点问题,落伍不落伍,而到那种程度,我认为不值得.没必要大家讨论个问题最后还要互相攻击.

其实,中间好多人回复的都是挺有道理的,语言嘛,工具而已,另外,世界上没有十全十美的事物(?),Cpp有点落伍又怎么样?不影响它是一门应用广泛的,甚至伟大的语言,也不影响我个人对Delphi的热爱,喜欢...

其实,我感觉好多东西大家自己也应该都是懂的,有时候不过不愿意口头承认,碍于面子或别的原因,不愿意直接说出来罢了.

好多东西楼上的都已经说过了,我也不再说了!

最后,祝大家工作顺利,生活开心!喜欢自己喜欢的语言,但不要"捍卫"自己的语言,有那功夫,整点高深的东西去.
shizaikanbuxiaqule 2008-08-09
  • 打赏
  • 举报
回复
LZ这个人就知道瞎咬人的,不要跟他辩.
看他在下面帖子里乱咬的情况吧:
http://topic.csdn.net/u/20080705/16/a9070b29-c658-47bc-8807-95b1d700a69f.html?seed=552069614
zwjchina 2008-07-11
  • 打赏
  • 举报
回复
支持楼主,我喜欢DelphiGUY。

我认为,C++这种在栈上建立对象的机制的确存在楼主所说的问题。
想在这一点上驳倒楼主的人应该都是徒劳的。

不过可以规定:
使用C++,只能通过new来建立对象,那么就可以比较容易的规避这个问题。

另外就是栈的大小是有限的,如果某个对象占用的空间很大,在一个递归过程中,又在栈上建立了该对象,
也很容易出现问题。

但是,不可否认的是,使用栈,速度会比使用堆快很多,那么对于严格使用引用对象模型的编程语言来说,
就不太可能使用栈的这一优势。从这个角度来看,C++可以在栈上建立对象就未必完全是坏事情。
ohyeahh 2008-06-03
  • 打赏
  • 举报
回复
通常只学习不冒泡的。
实在憋不住了
不管技术有多好或者多不好
楼主的为人实在不敢恭维~~~
ohyeahh 2008-06-03
  • 打赏
  • 举报
回复
要 要要
加载更多回复(363)

3,881

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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