C和CPP的区别 & C++,Java and Python的区别

简介:

今天在论坛上看到两个学神讨论C++的优劣性引申出来的各种问题,深深感觉自己差距很大,现就部分问题做个小的总结。

C和CPP的区别:

1. C没有bool类型。布尔类型是int。0是假,非0是真。 
  
2. C里字符常量(如'a'、'\n'、'\0'等)是int型,而C++里是char型。但这不影响使用。 
  
3. 没有引用类型的变量,一般使用指针。函数的参数也不能是引用类型,想要副作用请用指针。 
  
4. 没有模版。可以用宏代替。但是C99开始支持inline,用法和C++一样。 (C99 is an informal name of ISO/IEC 9899:1999, a past version of the C programming language standard)
  
5. 结构的类型是struct xxx,而不是xxx。如果你定义struct foo {int bar}; 那么你应该用sruct foo foo1;来创建变量foo1,而不是用C++的语法foo foo1;。如果愿意,你可以typedef一下。typedef struct foo foo_t; foo_t foo1;。 
  
6. 没有运行时类型机制,没有typeinfo,没有dynamic_cast。你自己知道对象是什么类型 
你可以把类型编码到对象里面。 
  
一般用tagged union思路:struct Value {int tag; union {int i; double d;} val;};,自己用tag标记是什么类型。 
  
也可以将一个公共的struct作为头;struct Animal {int kind}; struct Cat { struct Animal header; int extra_field;}; 
  
7. 没有面向对象编程。你需要自己实现多态。一般用函数指针。struct Animal {void (*speak)();}; 或者让对象指向一个虚函数表,避免每个对象里存大量的指针,但每次调用虚函数都会多一次内存访问。struct AnimalFuncs { void (*speak)()} cat_funcs, dog_funcs; struct Animal { struct AnimalFuncs funcs;}; struct Cat { struct Animal header; } cat1; ((struct Animal*)(&cat1))->funcs = cat_funcs; 所以,调用一次虚函数要访问多少次内存,你永远知道。 
  
8. 没有namespace,你要自己在函数前面加前缀,以避免冲突。 
  
*想一想,如果C++使用了namespace,那么编译出来的可执行文件里,符号表(函数名对应函数位置的表)中某个函数的名字应该怎么写(这可是关系到链接的时候能不能找到这个函数哦)?可能不同的namespace里有重名的函数,同一个也有重载的同名函数。就是这个简单的“符号表怎么写”的问题就够c++程序员折腾的。[二进制兼容性问题,C++的硬伤] 

*二进制兼容性 Application Binary Interface Transition(ABI Transition), 简单的说就是当程序已经编译完成产生了一个二进制文件,编译过程中依赖的某些头文件或者库文件,当这些文件发生更新升级时,二进制还能否正常运行?这里指的是动态库连接的二进制文件。
  
9. 没有string库,但是有string.h提供了字符串基本操作,你能想象到的几乎都有。C习惯用char型数组表示字符串,字符串以'\0'结尾。像其它函数传参数的时候,一般传指针,而不是拷贝字符串本身。如果你坚持要拷贝,请用strdup,并用free()回收内存。 
  
10. 没有iostream库,但有stdio.h。输出可以用printf,输入用scanf。文件操作用fopen,fread,fwrite,fclose,fseek,ftell,feof等,也有fprintf和fscanf。cout对应全局变量stdout,cin对应全局变量stdin,cerr对应stderr。你也可以直接用操作系统提供的open, read, write, close等调用。 
  
11. 没有new和delete。你可以使用malloc和free。它们在stdlib.h中。同样,小心内存碎片。 
  
12. 没有stl。但是如果你用C,大概说明你需要自己设计适合自己的应用的简单、专用而高效的数据结构。如果你用到了极其复杂的数据结构,说明你应该使用别的编程语言。 
  
p.s. Linux内核里的环形链表和红黑树实现不错。但是试试b-tree会不会更快。 
  
13. 你可以使用大量的第三方库和系统调用来弥补C语言标准库小的缺憾。正则表达式、网络、图形界面、数据库、国际化什么的都有。但是留意:有可能你需要换一个语言。不是所有的事都适合C做。毕竟C的定位是系统编程语言。 

C++,Java and Python 

1. 都是编程语言 
2. 都是图灵完备的编程语言 
3. 都是命令式语言 
4. 都是面向对象的语言 
5. 都是静态类型语言 
6. 都有大量的实际项目使用这两种语言 
7. 都对学术界和工业界产生了巨大的影响 
  
类型系统 
  
8. 都是静态类型语言。每个变量都有一个编译时就知道的类型。 
    * 与之相反,Python是动态类型语言,变量都是引用,变量没有类型,但值有类型。 
  
9. 基本数据类型都接近机器,如基本的整数、浮点数。C++的不必说,Java的int和long都是简单的32位和64位整数,float和double是IEEE754浮点数,boolean使用int存储,但boolean数组按每字节一个变量压缩存储。还有一个隐藏的“地址”类型,只有JVM能看到。 
    * 与之相反,Python的基本类型,如int,bool,str,都是对象。任何整数都是一个对象,有属性。 
  
10. 与第9条想对应的,基本运算符很接近机器的指令。如加减乘除、逻辑、移位、赋值等。Java甚至区分算术右移“>>>”和逻辑右移“>>”两种不同的右移运算。C++对应的分别是无符号整数和有符号整数的右移。 
    * 与之相反,Python的基本运算符都按方法实现。如1+2,实际上是调用1.__add__(2)方法。__add__方法可以被对象重写,以实现特殊的“加法”,如字符串相加。 
  
11. 都有基于类的复合类型系统。都支持面向对象编程的方法,包括继承、封装、多态。且都有一定的运行时类型信息(C++的typeinfo和dynamic_cast,Java的反射)
    * 与之相反,C语言没有类,在运行时也不知道一个指针指向什么类型的对象。 
  
语句 
  
12. 都有基本的结构化编程。顺序结构、选择结构(if, switch)、循环结构(while, do-while,for) 
    * 早期的一些语言依赖GOTO。 
  
13. 都有异常处理语法try-catch 
    * C没有异常处理 
    * Java有finally而C++依赖于栈上对象的析构函数。 
  
14. 都有函数(Java称为方法),都支持函数的递归调用。 
    * 早期的Fortran不支持递归调用,有的语言没有函数。 
  
15. 都支持按值传递。 
    * C++支持按引用传递。你可以将局部变量的“引用”传给函数,以改变变量的值。 
    * Java本质上只支持按值传递。引用类型可以认为引用本身是值,但是不能将局部变量“按引用传递”以改变局部变量。 
    * Python本质上只支持按值传递,原理和Java一样,可以理解为“引用”本身是值。而Python所有变量都是引用,甚至包括所有的整数,如42,也是将“42”这个对象的引用传入。但是整数、字符串等都是“不可变”(immutable)的类型,a=2; a=3实际上是创建一个新的对象“3”,把引用赋给a,而“2”这个对象仍然是2。你不能通过参数让另一个函数改变当前函数的局部变量。 
    * Haskell的所有函数调用都是按名传递。如果参数是一个表达式,那么这个参数不到需要求值的时候是不会求值的。而C++,Java,Python都必须先求参数值,后传入函数。 
  
面向对象编程 
  
16. 都有泛型系统。C++基于模板,为每种类型生成代码;而Java的泛型只在编译时用于检查,编译到JVM上则使用无类型的引用,运行时看不见类型参数。 
     * C没有。可以用void*指向任何东西。 
  
内存管理 
  
17. 都支持手动控制生存周期的内存管理(new),但C++要求手动回收(C++11有例外)。 
  
实现 
  
18. 编译:一般都是先编译,后执行。但C++是编译为本地代码,而Java一般先编译成bytecode。然后由JVM决定是解释执行还是编译成本地代码执行。 
     * Python, Ruby, JavaScript, PHP等脚本语言一般不预先编译,但运行时可以采用JIT Compiling策略。Haskell既可以解释又可以编译。LISP的执行过程就是源代码(S-Exp)的扩展、变换、展开的过程。 
  
19. 发布:一般都以二进制发布,但C++的二进制是本地代码,而Java是bytecode。 
     * Python一般直接发布源代码。罕见的一些闭源软件会发布bytecode。 
     * PHP也是。源代码直接嵌在网页代码中(或者说网页代码嵌在PHP代码中,怎么说都行) 
     * JavaScript也是,直接用源代码让浏览器解释。 
     * Haskell既可以解释,也可以编译,如何发布都行,看需要。 
  
20. 动态装载:依赖于实现,但C++、Java一般都支持。C++使用动态链接库,Java可以动态装载类。 
  
21. 外语接口:都可以与C语言交互。C++可以用extern "C"。Java需要JNI。 
  
都不具备的特性 
  
22. Tagged Union数据类型:带标记的联合类型,在函数式语言中很常见。但C++和Java可以用类和继承来模拟,也可以直接用if/else。 
     * Scala支持Case Class 
     * Haskell、ML的基本数据类型 
  
23. 模式匹配(Pattern Matching)结构,在函数式语言中很常见。但C++可以用dynamic_cast,Java可以用instanceof检测指针/引用的目标类型。 
     * Scala有match-case语句和unapply方法 
     * Ruby有case-when语句和模式匹配运算符“=~” 
     * Haskell、ML都有此类语句 
  
24. 复杂查询语句 
     * Python有List Comprehension。类似[len(x) for x in names if x.startswith("S")] 
     * Scala有For Comprehension。类似for(x <- names; if x.startswith("S")) yield x.size; 
     * C#有LINQ。类似from x in names where x.StartsWith("S") select s.length 
     * Ruby没有此类语句,但是ruby的函数调用很容易用块串接。 
  
25. lambda函数(C++11有例外)、闭包(C++11有例外)和高阶函数:将一个函数作为另一个函数的参数,即所谓“高阶函数”(C++是支持的,但在没有闭包的情况下很吃亏)。 
     * Python:filter(lambda x: x%2==0, [1,2,3,4,5,6,7,8,9,10]) 
     * JavaScript:connection.on_data(function(d) { buffer.add(d);}); 
     * Java可以用接口和对象来模拟函数作为参数:window.addEventListener(new EventListener(){@Override void onShow() { window.setTitle("Hello"); }}); 
  
26. coroutine(C++可以依赖库和系统调用实现) 
     * C:使用swapcontext或者longjmp模拟 
     * Python:几乎所有的for循环都依赖coroutine 
     * Ruby:Fiber 
     * JavaScript:Firefox17开始有实验性支持,但没有标准化。 
  
27. 动态对象:将一个对象的所有方法调用抽象成“方法名+参数”而不是具体的某个函数和参数。允许你做一些匪夷所思的事,比如将一个对象做“代理”,对它的所有方法调用将被记录方法名和参数,通过网络发送到远端,再将传回的数据翻译成基本数据类型作为返回值。 
     * Ruby里所有的对象都是这样做的。 
     * Python可以用__getattr__实现这种行为。Python用这种方法实现了XML-RPC。 
     * Java可以用java.lang.reflect.Proxy实现这个,也可以借助CGLib。 
  
28. 扩展方法:给一个类添加一个新的方法 
     * C#有extension method。 
     * Scala可以使用隐式类型转换,转换成一个封装类型,以造成“添加一个新方法”的假象。 
     * Haskell可以定义新的type class,将若干个已有的但不相干的类都定为成员。 
     * Ruby允许你随时重新打开一个类,随便加新方法。 
  
29. 嵌入式语言:作为另一个程序的一部分,用于程序扩展语言。显然C++和Java都不是为这个而设计的。 
     * Lua的解释器很小,适合嵌入另一个程序(如魔兽世界) 
     * Python相对大一些,但也适合做嵌入式脚本语言。 

目录
相关文章
|
4天前
|
存储 缓存 安全
java 中操作字符串都有哪些类,它们之间有什么区别
Java中操作字符串的类主要有String、StringBuilder和StringBuffer。String是不可变的,每次操作都会生成新对象;StringBuilder和StringBuffer都是可变的,但StringBuilder是非线程安全的,而StringBuffer是线程安全的,因此性能略低。
|
21天前
|
Java
Java代码解释++i和i++的五个主要区别
本文介绍了前缀递增(++i)和后缀递增(i++)的区别。两者在独立语句中无差异,但在赋值表达式中,i++ 返回原值,++i 返回新值;在复杂表达式中计算顺序不同;在循环中虽结果相同但使用方式有别。最后通过 `Counter` 类模拟了两者的内部实现原理。
Java代码解释++i和i++的五个主要区别
WK
|
23天前
|
安全 Java 编译器
C++和Java哪个更好用
C++和Java各具优势,选择取决于项目需求、开发者偏好及目标平台特性。C++性能出色,适合游戏、实时系统等;Java平台独立性强,适合跨平台、安全敏感应用。C++提供硬件访问和灵活编程范式,Java有自动内存管理和丰富库支持。两者各有千秋,需根据具体需求选择。
WK
17 1
|
28天前
|
IDE Java 程序员
C++ 程序员的 Java 指南
一个 C++ 程序员自己总结的 Java 学习中应该注意的点。
22 5
|
30天前
|
存储 安全 编译器
在 C++中,引用和指针的区别
在C++中,引用和指针都是用于间接访问对象的工具,但它们有显著区别。引用是对象的别名,必须在定义时初始化且不可重新绑定;指针是一个变量,可以指向不同对象,也可为空。引用更安全,指针更灵活。
|
29天前
|
Java
通过Java代码解释成员变量(实例变量)和局部变量的区别
本文通过一个Java示例,详细解释了成员变量(实例变量)和局部变量的区别。成员变量属于类的一部分,每个对象有独立的副本;局部变量则在方法或代码块内部声明,作用范围仅限于此。示例代码展示了如何在类中声明和使用这两种变量。
|
1月前
|
Java
Java基础之 JDK8 HashMap 源码分析(中间写出与JDK7的区别)
这篇文章详细分析了Java中HashMap的源码,包括JDK8与JDK7的区别、构造函数、put和get方法的实现,以及位运算法的应用,并讨论了JDK8中的优化,如链表转红黑树的阈值和扩容机制。
27 1
|
1月前
|
C++ Python
探索Python与C/C++混合编程的艺术
探索Python与C/C++混合编程的艺术
38 1
|
1月前
|
Java 编译器 C语言
【一步一步了解Java系列】:探索Java基本类型与C语言的区别
【一步一步了解Java系列】:探索Java基本类型与C语言的区别
45 2
WK
|
22天前
|
开发框架 移动开发 Java
C++和Java哪个更适合开发移动应用
本文对比了C++和Java在移动应用开发中的优劣,从市场需求、学习难度、开发效率、跨平台性和应用领域等方面进行了详细分析。Java在Android开发中占据优势,而C++则适合对性能要求较高的场景。选择应根据具体需求和个人偏好综合考虑。
WK
39 0
下一篇
无影云桌面