正如我之前在这里发布的那样,我决定尝试其中一个但是考虑到我作为Web开发人员的兴趣,我想知道它们在实际应用程序中的区别.
编辑注意:
虽然我是网络开发人员,但请不要限制你的答案.我才30岁......我已经有了多年的职业生涯改变.
请记住,我说ASFAC++乙.:)我把最重要的差异化因素放在第一位.
垃圾收集
垃圾收集(GC)是区分这些语言的最重要因素.
虽然C和C++可以与GC一起使用,但它是一个事后的想法,并且不能使其工作(最着名的是这里) - 它必须是"保守的",这意味着它不能收集所有未使用的内存.
C#从一开始就设计用于GC平台,标准库也是这样设计的.它对开发人员的工作效率产生了绝对的根本性差异,必须要经历这一点.
C/C++用户普遍认为GC等同于"糟糕的性能".但这是过时的民间传说(即使是C/C++上的Boehm收藏家也比大多数人预期的要好得多).典型的恐惧是程序停止的"长时间暂停",因此GC可以做一些工作.但实际上这些长时间暂停发生在非GC程序中,因为它们运行在虚拟内存系统之上,有时会中断在物理内存和磁盘之间移动数据.
人们普遍认为GC可以用shared_ptr替换,但它不能; 具有讽刺意味的是,在多线程程序中,shared_ptr
比基于GC的系统慢.
有些环境非常节俭,GC不实用 - 但这些环境越来越少见.手机通常有GC.C#通常运行的CLR GC似乎是最先进的.
自从大约18个月前采用C#以来,我已经经历了使用分析器进行纯性能调整的几个阶段,并且GC非常高效,在程序运行期间几乎不可见.
GC不是灵丹妙药,它不能解决所有的编程问题,它只是真正清理内存分配,如果你分配的是非常大的内存块,那么你仍然需要注意,并且它仍然可以有什么相当于一个足够复杂的程序中的内存泄漏 - 然而,GC对生产力的影响使其非常接近灵丹妙药!
未定义的行为
C++建立在未定义行为的概念之上.也就是说,语言规范定义了语言特征的某些狭义定义用法的结果,并将所有其他用法描述为导致未定义的行为,原则上意味着操作可能有任何结果(实际上这意味着难以诊断)涉及明显不确定的数据损坏的错误).
几乎所有关于C++的内容都涉及未定义的行为.即使非常好的即将发布的功能(如lambda表达式)也可以轻松地用作破坏堆栈的便捷方法(通过引用捕获本地,允许lambda实例比本地更长).
C#建立在所有可能的操作都应该定义行为的原则之上.可能发生的最坏情况是抛出异常.这彻底改变了软件构建的体验.
(存在不安全模式,它具有指针,因此具有未定义的行为,但强烈建议不要使用 - 请将其视为与嵌入式汇编语言类似.)
复杂
就复杂性而言,必须特别挑选C++,特别是如果我们考虑很快就要标准化的新版本.C++完全可以使其自身有效,而不是假设GC,因此它具有令人敬畏的学习曲线.语言设计者通过说"这些功能仅适用于图书馆作者而非普通用户"来解释大部分内容 - 但要在任何语言中真正有效,您需要将代码构建为可重用的库.所以你无法逃脱.
从积极的方面来说,C++是如此复杂,它就像一个书呆子的游乐场!我可以向您保证,您将学到如何将它们融合在一起,这将会有很多乐趣.但我不能认真地推荐它作为主流平台上富有成效的新作品(哦,浪费的岁月......)的基础.
C保持语言简单(在"编译器易于编写"的意义上简单),但这使编码技术更加神秘.
请注意,并非所有新语言功能都等同于增加的复杂性.一些语言特性被描述为"语法糖",因为它们是编译器为您扩展的简写.这是思考近年来C#的大量增强的好方法.语言标准甚至通过将翻译转换为longhand来指定一些特征,例如using
语句扩展为try
/ finally
.
有一次,可以以相同的方式考虑C++模板.但是它们已经变得如此强大,以至于它们现在构成了语言的一个独立维度的基础,拥有自己热情的用户社区和习语.
图书馆
关于C和C++最奇怪的是它们没有标准的可互换形式的预编译库.将其他人的代码集成到您的项目中总是有点繁琐,有关您将如何链接到它的晦涩决定.
此外,标准库非常基础--C++有一套完整的数据结构和表示字符串(std::string
)的方法,但这仍然是最小的.有没有找到目录中文件列表的标准方法?太棒了,不!是否有解析或生成XML的标准库支持?不.访问数据库怎么样?严肃点!写一个网站后端?你疯了吗?等等
所以你必须去更远的地方打猎.对于XML,请尝试Xerces.但它用于std::string
表示字符串吗?当然不是!
所有这些第三方图书馆都有自己的命名类和功能的奇怪习俗吗?完全正确!
C#的情况不可能更加不同; 基础知识从一开始就存在,所以一切都很好地互操作(因为基础是由CLR提供的,所以有跨语言支持).
这并不完美; 仿制药应该从一开始就存在但不是,这确实会在一些较旧的图书馆留下明显的痕迹; 但从外部解决这个问题通常都是微不足道的.此外,许多流行的库都是从Java移植而来的,这不像它最初出现的那么好.
闭包(具有局部变量捕获的匿名方法)
Java和C实际上是缺少闭包的最后剩下的主流语言,并且库可以设计和使用得更加整齐,而不是没有(这就是为什么移植的Java库有时看起来对C#用户来说很笨的原因).
关于C++的有趣之处在于它的标准库被设计成就像语言中的闭包一样(容器类型
,
).然后十年过去了,现在他们终于被添加了!它们将产生巨大的影响(尽管如上所述,它们会泄漏不明确的行为).
C#和JavaScript是使用最广泛的语言,其中闭包是"惯用的".(这些语言之间的主要区别在于,当动态键入JavaScript时,C#是静态类型的).
平台支持
我把它放在最后只是因为它似乎没有像你想象的那样区分这些语言.所有这些语言都可以在多个操作系统和机器架构上运行.C是最广泛支持的,然后是C++,最后是C#(尽管C#可以在大多数主要平台上使用,这要归功于一个名为Mono的开源实现).
我在Windows和各种Unix风格之间移植C++程序的经历令人不快.我从来没有尝试将C#中任何非常复杂的东西移植到Mono,所以我不能对此发表评论.
C和C++都为您提供了较低级别的抽象,随着复杂性的增加,它提供了对底层机器功能的广泛访问,这些功能不一定会被其他语言暴露.与C相比,C++增加了完全面向对象语言的便利性(缩短了开发时间),这可能会增加额外的性能成本.就真实世界的应用程序而言,我认为这些语言适用于以下领域:
C
内核级软件.
硬件设备驱动程序
需要访问旧的稳定代码的应用程序.
C,C++
应用程序或服务器开发需要对内存管理进行微调(并且不能留给通用垃圾收集解决方案).
需要访问与更现代的托管语言不能很好地连接的库的开发环境.
虽然托管C++可用于访问.NET框架,但它不是无缝过渡.
C#提供了一个托管内存模型,可以再次添加更高级别的抽象.这种抽象级别增加了便利性并缩短了开发时间,但使对较低级别API的访问变得复杂,并使专门的性能要求成为问题.
在托管内存环境中实现极高性能的软件当然是可能的,但对其含义的认识至关重要.
C#的语法肯定比C/C++要求更低(并且容易出错),并且对于启动的程序员来说,学习曲线较浅.
C#
快速客户端应用开发.
高性能服务器开发(例如StackOverflow),受益于.NET框架.
需要.NET框架优势的应用程序,其语言是为其设计的.
JohannesRössel提出了一个有效的观点,即使用C#指针,不安全和未经检查的关键字突破了构建C#的抽象层.我要强调的是,编程类型是大多数C#开发方案的例外,而不是语言的基本部分(与C/C++一样).
C是简单,干净的语言,让你自己做所有事情.它不会牵你的手,也不能阻止你在脚下射击.但它拥有你想做的一切.
C++是添加了类的C,然后是一大堆其他的东西,然后是更多的东西.它不会牵你的手,但它会让你自己动手,附加GC,或RAII和智能指针.如果你想要完成某些事情,很可能有一种滥用模板系统的方法,为你提供一个相对简单的语法.(还有C++ 0x).这种复杂性还使你有能力意外地创造了十几个你自己的实例并将它们全部射入脚中.
C#是微软在改进C++和Java方面的努力.大量的语法特征,但没有接近C++的复杂性.它在完全托管的环境中运行,因此可以为您完成内存管理.如果你需要,它会让你"变脏"并使用不安全的代码,但这不是默认代码,你必须做一些自己拍摄的工作.
我的观点是C#和ASP.NET将是三个最好的开发网络偏见.
我怀疑是否有人用C或C++编写新的Web应用程序了.它是在10年前完成的,并且很可能仍有大量遗留代码在使用,但它们并不是特别适合,似乎没有那么多(正在进行的)工具支持,并且它们可能只有一个小的活动进行Web开发的社区(除了Web服务器开发之外).我在当天写了许多网站C++ COM对象,但是C#的效率要高得多,除非你需要,否则没有令人信服的理由来编写C或C++(在这种情况下).
如果有必要,我仍然会编写C++,但它通常用于一个小问题域.例如,从C#通过P/Invoke传递到旧的C风格的dll - 在C#中做一些彻头彻尾的笨拙的东西,轻而易举地创建一个C++ COM对象作为桥梁.
C#的优点在于,您还可以轻松转换为编写Windows和控制台应用程序并保留在C#中.使用Mono,您也不仅限于Windows(尽管您可能只限于使用哪些库).
无论如何,这都是从网络偏见的角度出发的.如果你问过嵌入式设备,我会说C或C++.您可以说这些都不适合Web开发,但C#/ ASP.NET非常流畅,运行良好,有大量的在线资源,庞大的社区和免费的开发工具.
因此,从现实世界的角度来看,只根据要求选择C#,C++和C中的一个,作为一般规则,你最好坚持使用C#.