我只有20分。我需要把java代码转成C或C++代码,三维数组字符指针 字符数组很少用到,头大..

C++语言中数组指针和指针数组彻底分析_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
C++语言中数组指针和指针数组彻底分析
||暂无简介
总评分3.8|
阅读已结束,如果下载本文需要使用2下载券
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩15页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢个人声明,源自: 邮箱: VC++ .net OpenGL QQ:在windows下使用SWIG的环境配置问题(将c/c++转为java语言)在Windows下安装:SWIG的安装不同于一般的Windows安装程序,它相对而言更加容易上手。主要的步骤如下:1.从SWIG网站下载swigwin压缩包然后解压缩到一个目录。这就是我们下载Windows平台下的版本的所有事情。2.像Swig Windows 例子部分描述的设置环境变量来用Visual C++运行案例. Java下环境变量的设置:
JAVA_INCLUDE : Set this to the directory containing jni.h JAVA_BIN : Set this to the bin directory containing javac.exe Example using JDK1.3: JAVA_INCLUDE: d:\jdk1.3\include JAVA_BIN: d:\jdk1.3\bin在win2000系统的环境参数中添加两个新的变量JAVA_INCLUDE和AVA_BIN,值分别为d:\jdk1.3\include和d:\jdk1.3\bin。即对应的java的安装目录//////////////////////////////////////////////////////////////////////////////////////////////////SWIG对c/c++中对象和类型的支持?ANSI C (标准C)SWIG能够打包封装的标准C对象包括:1.所有标准C数据类型 2.全局函数,全局变量,和常量3.结构体和联合体 4.指针5.数组和多维数组6.指针函数 7.可变长度的参数. 8.类型定义Typedef 9.枚举EnumsANSI C++ (标准C++)SWIG提供对几乎所有标准C++对象的封装:1.所有C++数据类型2.参数 3.成员指针 4.类 5.继承和多重继承 6.重载函数和方法(使用动态接口)7.重载操作8.静态成员9.命名空间(包括使用声明,别名,嵌套,等)10.模板11.成员模板12.特殊模板和部分特殊应用13.Smart指针14.支持strings,STL vector等的库The only major C++ feature not currently supported by SWIG is the wrapping of nested classes--a problem we're working on. SWIG also does not allow C++ virtual methods to be implemented in certain target languages (a subtle feature that might be useful in projects that rely heavily on the use of callback functions). C++ users who rely on advanced template programming techniques (e.g., template meta-programming) should also be aware that SWIG currently requires manual instantiation of all template classes. Therefore, if your application somehow involves the instantiation of 50000 template classes, your mileage might vary.////////////////////////////////////////////////////////////////////////////////////////////////SWIG输入数据格式:在输入上,SWIG需要包括C/C++声明和特殊的SWIG指示的一个文件。大部分来说, 这是一个特殊的SWIG接口文件通常是特指.i或.swg的文件格式。在特殊的情况下,SWIG能直接被用于原始的头文件或源文件。但是,这并不是最通常的典型使用案例而且会有几种原因使你不会想这样做(原因在后面会讲述)。最通常的SWIG接口文件格式如下:%module mymodule %{#include "myheader.h"%}// Now list ANSI C/C++ declarationsint bar(int x);...模块名由指定的%module来给出(或者用-module命令行选项).这段指示性文字必须写在文件的头部并且在使用时将这个模块名作为扩展模块对象来使用(此外,这个模块名经常在目标语言中被定义成一个命名空间来使用)。如果模块名在命令行已经被给出了,系统将不考虑由%module标示的模块名了。所有在%{...%}块内的东西将被简单作为结果逐字拷贝到SWIG创建的wrapper(包装)文件中。这部分大部分被用来包括头文件和生成wrapper代码需要的其它声明。这里很重要的强调一点因为你在一个SWIG的输入文件中包含了一个声明,这个声明并不自动显示在生成的wrapper代码中———因此你需要确信你确实把正确的头文件在%{ ... %}部分中。这里应该指出SWIG不解析和解释附在%{ ... %}部分的文字。SWIG的%{...%}内的语法和语义很类似于输入文件中的声明部分???/////////////////////////////////////////////////////////////////////////////////////////////////////SWIG使用说明 1.编写interface文件example.i
如果api有头文件就更简单了,下面的代码定义一个example类
////example.i文件
%module example %{ #include "example.h" %} %include "example.h"
swig -java example.i
生成符合JNI语法(见上)的C文件: example_wrap.c
生成Java类文件:exampleJNI.java,example.java swig -c++ -java example.i 同时生成example_wrap.c 文件
3.VC把example_wrap.c 和example.c 打包成dll.
4.在普通java程序里使用example.java
System.loadLibrary("example");
int g = new Example().add(42,105); //////////////////////////////////////////////////////////////////////////////////////////////////STL/C++库的转化这一部分的库模块提供访问部分标准C++库包括STL的方法。使SWIG支持STL还是一个正在努力中的事情。SWIG对于一些语言模块的支持使较全面的但是对很少用到的库则支持的很少。下面就是表示了C++类和支持的C++库 以及SWIG接口文件的对应表C++ class
C++ Library file
SWIG Interface library file std::deque
std_deque.i std::list
std_list.i std::map
std_map.i std::pair
std_pair.i std::set
std_set.i std::string
std_string.i std::vector
std_vector.i 这个表应该说还没有很完善。一些语言模块支持上面的一个子集而另一些支持扩展的STL类.请仔细寻找相关语言库目录下的库文件。1.std_string.i这个std_string.i库提供将C++ std::string对象转化为目标描述性语言的方法。举例:(在example.i中)%module example%include "std_string.i"std::string foo();void
bar(const std::string &x);在目标语言中:x = foo();
# Returns a string objectbar("Hello World");
# Pass string as std::string人们碰到的一个最常见的问题是在 类/结构 中包含一个 std::string。这个问题可以通过定义一个typemap来解决。例如:%module example%include "std_string.i"%apply const std::string& {std::string* foo};struct my_struct{
std::};在目标语言中:x = my_struct();x.foo="Hello World";
# assign with stringprint x.
# print as string这个模块只支持std::string 和 const std::string &两种写法。指针和 非常量参数将被无修改的保留下来并作为SWIG的指针返回。库文件完全识别C++的命名空间。如果你输出std::string 或 将它重命名为另一种类型。请确认你将此重命名声明包含到了你的接口文件中。例如:%module example%include "std_string.i"typedef std::string S...void foo(string s, const String &t);
// std_string typemaps still applied注:std_string库转换为Perl时在某些系统平台下出现不兼容性。我们正在查找原因。-----------------------------------------------------------------------------------------------2.std_vector.istd_vector.i库提供了对C++ STL中的vector类的支持。使用此库通常包括使用%template 标识。你所需要做的就是分清你要使用的vector中的数据类型。例如:%module example%include "std_vector.i"namespace std {
%template(vectori) vector&int&;
%template(vectord) vector&double&;};/////////////////////////////////////////////////////////////////////////////////////////////////////////SWIG 对C++类继承的支持SWIG支持单继承,一般可以很好的将单继承的类转为java对象。对多继承支持的程度不太好,需要人工参与.i文件的修改,详细请查找资料。/////////////////////////////////////////////////////////////////////////////////////////////////////////SWIG封装包不支持以下的C++语法:1.重载方法和重载函数。SWIG封装不知道如何解决同名冲突因此你必须给每一个同名重载方法一个替换的名称,具体方法是用%name如下所示:void foo(int a);
%name(foo2) void foo(double a, double b);2.重载操作???。并不完全支持。对此唯一的工作区是写一个帮助函数。例如:%inline %{
Vector *vector_add(Vector *a, Vector *b) {
... whatever ...
}%}3.命名空间。不完全支持。直到SWIG2.0发布以前将不会得到支持。//////////////////////////////////////////////////////////////////////////////////////////////////////////在VC++6.0的.dsp工程设置文件中配置SWIG调用举例说明:1.首先在Project-&Settings-&Post-build step选项卡下Post-build description文字框中输入Java compile post-build step在下面的commands中添加echo on"%JAVA_BIN%\javac" *.java这两句话的意思是编译完后调用javac将当前编译路径下的所有.java文件编译成.class二进制文件。2.然后用写字版打开.dsp文件在文件的倒数第四行# Begin Source File后添加SOURCE=.\example.i
#DEBUG版本情况下的设置!IF
"$(CFG)" == "example - Win32 Debug"# Begin Custom Build 开始客户方生成InputPath=.\example.iInputName=example"$(InputName)_wrap.cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" echo In order to function correctly, please ensure the following environment variables are correctly set:
echo JAVA_INCLUDE: %JAVA_INCLUDE%
echo JAVA_BIN: %JAVA_BIN%
..\..\..\swig.exe -c++ -java $(InputPath)
# End Custom Build 结束客户方生成#RELEASE版本情况下的设置!ELSEIF
"$(CFG)" == "example - Win32 Release"# Begin Custom Build 开始客户方生成#指定输入路径和输入名称InputPath=.\example.iInputName=example#调用swig -c++ -java生成对应的java文件(.java)"$(InputName)_wrap.cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" echo In order to function correctly, please ensure the following environment variables are correctly set:
echo JAVA_INCLUDE: %JAVA_INCLUDE%
echo JAVA_BIN: %JAVA_BIN%
..\..\..\swig.exe -c++ -java $(InputPath)
# End Custom Build 结束客户方生成
如果您想留下此文,您可以将其发送至您的邮箱(将同时以邮件内容&PDF形式发送)
相关文章推荐
(Ctrl+Enter提交) &&
已有0人在此发表见解
&在& 19:07收藏到了
&&在信息爆炸的时代,您的知识需要整理,沉淀,积累!Lai18为您提供一个简单实用的文章整理收藏工具,在这里您可以收藏对您有用的技术文章,自由分门别类,在整理的过程中,用心梳理自己的知识!相信,用不了多久,您收藏整理的文章将是您一生的知识宝库!
· 蜀ICP备号-1指针对于新手来说是一件非常头疼的事情,特别是二重指针,第一此看的时候一知半解的,在拥有一定的代码量之后,终于鼓起勇气再看一遍,其他指针的知识点还好,到了二重指针、函数指针这里就有些难度了,多看了些资料,终于把它攻克了,下面把资料整理出来,以供大家参考:
首先鸣谢以下资料,如果作者有哪些讲得不清楚的可以参考一下下面资料,这篇文章就是根据下面资料整理出来的:
b.com/ggjucheng/archive//2286391.html
/gmh915/archive//1756067.html
在讲二重指针之前,我觉得有必要了解一下指针的运算:
指针的算术运算
指针可以加上或减去一个整数。指针的这种运算的和通常的数值的加减运算的意义是不一样的。例如:??例二:??
?char a[20];?
?int *ptr=a;?
在上例中,指针ptr的类型是int*,它指向的类型是int,它被初始化为指向整形变量a。接下来的第3句中,指针ptr被加了1,编译器是这样处理的:它把指针ptr的值加上了sizeof(int),在32位程序中,是被加上了4。由于地址是用字节做单位的,故ptr所指向的地址由原来的变量a的地址向高地址方向增加了4个字节。由于char类型的长度是一个字节,所以,原来ptr是指向数组a的第0号单元开始的四个字节,此时指向了数组a中从第4号单元开始的四个字节。
下面我们来看看各种数据类型在32位和64位下的字节数:
常用数据类型对应字节数??可用如sizeof(char),sizeof(char*)等得出
?32位编译器:
??????char :1个字节??????char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器)??????short int : 2个字节 ??????int:??4个字节??????unsigned int : 4个字节 ??????float:??4个字节 ??????double:???8个字节 ??????long:???4个字节 ??????long long:??8个字节 ??????unsigned long:??4个字节&!--[if !supportLineBreakNewLine]--&&!--[endif]--&
??64位编译器:
??????char :1个字节 ??????char*(即指针变量): 8个字节??????short int : 2个字节 ??????int:??4个字节??????unsigned int : 4个字节 ??????float:??4个字节 ??????double:???8个字节 ??????long:???8个字节??????long long:??8个字节 ??????unsigned long:??8个字节
指针的指针和数组指针
此图清晰地解释了二重指针以及指针和数组的关系:
请看以下代码:
#include&iostream&
usingnamespace
int main(){
???????? int tab[8] = { 3, 4, 2, 6, 7, 9 };
???????? int tab2[3][4] = { 3, 4, 2, 6, 7, 9 };
???????? cout && *(tab + 3) &&//结果为6,指针指向int型,加1移动4个字节,加3移动12个字节
???????? cout && tab[5] &&//结果为9,不解释
???????? cout && *(&tab[6]) &&//结果为0
???????? cout && *(*(tab2 + 1)) &&//*(tab2+1)为指针指向tab2[1][0],因此其结果为7
???????? cout && *(&tab2[0][0] + 1) &&//结果为4
???????? cout && *(tab2 + 1) &&
???????? cout && &tab2[1][0] &&
???????? cout && *(*(tab2 + 1))+1 &&
???????? ("pause");
结果及理由如上图所示。弄懂这结果是怎样来的你就基本掌握了。
int array[10];?
int (*ptr)[10];?
ptr=&? 上例中ptr是一个指针,它的类型是int (*)[10],他指向的类型是int [10],我们用整个数组的首地址来初始化它。在语句ptr=&array中,array代表数组本身。
这句话看起来比较难,所以我们可以另一个来理解:
?????? ???????? int *abcde = NULL;
???????? int abcd[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
???????? int abc[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
???????? int **pointer2=&
???????? int(*pointer)[10] = &
???????? cout && "porinter:" &&
???????? cout && *(*pointer+1) &&
???????? cout && *(*pointer) &&
???????? cout && "*porinter,&pointer[0]指针的值" &&
???????? cout && *pointer &&
???????? cout && &pointer[0] &&
???????? cout && "porinter,abcd,pointer指针的值" &&
???????? cout && abcd &&
???????? cout && pointer2 &&
???????? cout && pointer &&
???????? cout && "porinter,abcd,pointer长度" &&
???????? cout && sizeof(abcd) &&
???????? cout && sizeof(pointer2) &&
???????? cout && sizeof(pointer) &&
???????? system("pause");
输出结果为:
如果让 (*pointer)[10] = & abcd[9]则会报错:(*)[9]类型的值不能指向(*)类型的实体;
所以通过这样的对比,应该可以比较容易地理解什么叫做pointer的指针类型是(*)[10],指向array[10]了吧
指针函数和函数指针:
指针函数和函数指针听起来很费解,但理解起来却并不见得比前面那位难:
指针函数是函数:指针函数本质是函数,它的返回值是指针,所以被称作指针函数。
函数指针是指针:函数指针的本质是指针,它指向函数,通过函数指针可以调用函数。
指针函数本质是函数,它的返回值是指针,所以被称作指针函数
函数指针的本质是指针,它指向函数,通过函数指针可以调用函数
void ?main()
???????? int wk,
???????? do
???????? {
?????????????????? printf("Enter week(1 - 5)day(1 - 7)\n");
?????????????????? sf("%d%d", &wk, &dy);
???????? } while (wk&1 || wk&5 || dy&1 || dy&7);
???????? printf("%d\n", *GetDate(wk, dy));
???????? system("pause");
int * GetDate(intwk, intdy)
???????? staticint calendar[5][7] =
???????? {
?????????????????? { 1, 2, 3, 4, 5, 6, 7 },
?????????????????? { 8, 9, 10, 11, 12, 13, 14 },
?????????????????? { 15, 16, 17, 18, 19, 20, 21 },
?????????????????? { 22, 23, 24, 25, 26, 27, 28 },
?????????????????? { 29, 30, 31, -1 }
???????? };
???????? return &calendar[wk - 1][dy - 1];
void(*funcp)();
void FileFunc(), EditFunc();
void main()
???????? funcp = FileF
???????? (*funcp)();
???????? funcp = EditF
???????? (*funcp)();
???????? system("pause");
void FileFunc()
???????? printf("FileFunc\n");
void EditFunc()
???????? printf("EditFunc\n");
????当一个函数声明其返回值为一个指针时,实际上就是返回一个地址给调用函数,以用于需要指针或地址的中。????格式:?????????类型说明符?*?函数名(参数) ????当然了,由于返回的是一个地址,所以类型说明符一般都是int。????例如:int?*GetDate(); ??????????int?*?aaa(int,int); ????的是一个地址值,经常使用在返回数组的某一元素地址上。
int (*f) (int x); /*?声明一个函数指针?*/
 f= /*?将func函数的首地址赋给指针f */
指向函数的指针包含了函数的地址,可以通过它来调用函数。声明格式如下:????????类型说明符?(*函数名)(参数) ????其实这里不能称为函数名,应该叫做指针的变量名。这个特殊的指针指向一个返回整型值的函数。指针的声明笔削和它指向函数的声明保持一致。????????指针名和指针运算符外面的括号改变了默认的运算符优先级。如果没有圆括号,就变成了一个返回整型指针的函数的原型声明。
指针函数问题解决了,但是还是有很多小的问题,我在网上看面试题的时候,遇到了这样一个问题:
参考:(/iuices/archive//2234877.html)
下面几种方式哪种可以实现交换?
void swap1(intp, intq)
???????? int temp = NULL;
???????? temp = p;
???????? p = q;
???????? q =
void swap2(int *p, int *q)
???????? int *temp=NULL;
???????? *temp = *p;
???????? *p = *q;
???????? *q = *
void swap3(int *p, int *q)
???????? int *temp = NULL;
???????? temp = p;
???????? p = q;
???????? q =
void swap4(int *p, int *q)
???????? int temp = NULL;
???????? temp = *p;
???????? *p = *q;
???????? *q =
void swap5(int &p, int &q)
???????? int temp = NULL;
???????? temp = p;
???????? p = q;
???????? q =
答案是4和5,代码在附件里有哦。
还有一题是考char str[]和char *str的区别的:
这个函数有什么问题?该如何修改?
char?*strA()
????char?str[] = "hello world";
????return?
:这个str里存在的地址是函数strA栈里“hello world”的首地址。函数调用完成,栈帧恢复调用strA之前的状态,临时空间被重置,“回缩”,strA栈帧不再属于应该访问的范围。这段程序可以正确输出结果,但是这种访问方法违背了函数的栈帧机制。
????? 但是只要另外一个函数调用的话,你就会,这种方式的不及性。
????? 如果想获得正确的函数,改成下面这样就可以:
char?*strA()
????char?*str = "hello world";
????return?
????? 首先要搞清楚char *str 和 char str[] :
char?str[] = "hello world";
是分配一个局部数组。局部数组是局部变量,它所对应的是中的栈。局部变量的生命周期结束后该变量不存在了。
char?*str = "hello world";
str[]和*str的区别:
其实区别主要在两个地方http://blog.csdn.net/szchtx/article/details/:
弄清第一点区别首先要明白常量指针和指针常量的区别:
const char *p; 常量指针,指向一块区域,这块区域不可写,只能读。 char * 指针常量,指向一块区域,这块区域可读可写,但是指针的值初始后就不能改,类似于一般常量。
[cpp]?view plaincopyprint?
char?ss[]="C++";??
ss[0]='c';??????????????????//?合法??
char?*p="C++";??
p[0]='c';???????????????????//?合法但不正确??
该段代码在下编译可以通过,但是运行时程序会停止工作,为什么呢?原因在于p[0]='c'这一语句。该语句试图修改p指向的字符串的首个字符,出现了。
原因在于两种方式对字符数组操作的机制不同。使用char *p="C++"语句后,编译器在内存的文字常量区分配一块内存,保存”C++“这一字符串字面值,然后在栈上分配内存保存p,p的内容为"C++"的地址。p[0]='c'试图修改常量”C++“,程序当然就会崩溃了。而char ss[]="C++"语句,定义了一个数组,编译器为其在栈上分配了内存空间,因而可以进行修改操作。
因此,可以总结如下:
(1)char ss[]定义了一个数组,ss可认为是一个常指针,ss不可改变,但ss指向的内容可以发生改变。
(2)char *p定义了一个可变指针,p可以指向其它对象。但对于char *p=”abc“这样的情况,p指向的是常量,故内容不能改变。
如下代码进一步说明char ss[]和char *p的区别:
[cpp]?view plaincopyprint?
char?*strA()??
????char?str[]="Hello";??
????return???
调用该函数,不一定能够得到正确的结果。因为str定义了一个局部数据,是局部变量,存在于函数strA中的栈帧中。当函数调用完成后,栈帧恢复到函数strA调用前的状态,临时空间被重置,为函数分配的栈空间被收回,str所指向的地址也就不存在了。
将上述代码修改:
char?*strA()??
????char?*str="Hello";??
????return???
该函数能够正常运行,因为str指向的字符串字面值被保存在只读的数据段,是的,当函数调用完成后,str指向的地址未发生变化。
综上,可以看出使用char []较容易出错,可能出现不确定的结果。C++提供的string类相比之下,要安全的多了。
其实以上解释并不是很易懂,我也不是很懂,其实对C++内存分区不懂得话学习C++是很吃力的,所以附上链接,希望对有需要的朋友有帮助:/hanyonglu/archive//2014212.html
指针的题目有难有易,不过指针这种不是靠做题就能会的,实际灵活运用,才是王道。C++的学习之路远没有结束,哪怕看再多的资料也要躬身学习。如果感觉这些资料对你未来的学习有帮助,就足够了。附上自己整理的代码,希望能对大家有所帮助,再次感谢博客园的大神们~~~
最后知识点梳理,这篇文章介绍了:
1、指针运算;2、指针的指针;3、数组指针;4、指针函数和函数指针的区别;5、指针常量和常量指针的区别;6、char str[] 和char *str的区别;
code.rar (1.2 KB)
下载次数: 0
查看图片附件Java VS C/C++ 运行速度的对比 -
- ITeye技术网站
博客分类:
1.1 Java VS C/C++
Java与C++相比的优点在于:
Java比C,C++简单,学起来比C\C++容易
Java完全对象化,比如数组在Java中是一个对象,含有length这个属性;而不像C++中数组是一个指针。所以访问数组,Java都会进行边界检查,更安全,但牺牲了速度。同时因为Java中所有类都会继承Object基类,所以可以把几个好不相干的类用基类联系起来,比如放在同一个数组里。
Java中没有指针的概念。
Java中有完善的内存管理机制,能自动垃圾回收,最大可能降低内存溢出的可能,同时提高编程效率。
Java中有完善的异常机制(标准C++中不够完善)。
java中保持数据时对象本身是在堆里,同时靠一在栈里的句柄与之连接。这个设计更合理。
Java标准库完整的多,相比之下C++除了一个STL(而且还超级难用)就没了,实际C++编程中需要大量使用第3方库。这很大程度上是因为Java有一些商业公司支持,更新速度快,而C++只有一个可怜的标准委员会,上一个C++标准版本还是C++98。
Java因为是把程序编译为字节码,运行时需要JVM把字节码再翻译为机器码,所以他跨平台,一次编译到处运行。但这也是他慢的根本原因。
Java原生支持多线程(C++仅靠标准库办不到),原生的UI,如AWT Swing。
C++与Java相比的优点在于:
Java比C\C++慢。Java 1.0 比C慢20倍 现在的Java 1.6运行速度也只是C的一半。
C++在继承和派生上比Java更灵活。
C++ 中可以直接插入汇编 能直接操控底层硬件 所以操作系统还是得用c写。
Java办的到C++一定办得到,C++办得到的Java则不一定。
Sun被甲骨文收购了之后,Java的发展很受影响。
C++编译的程序可以直接运行,Java需要安装JRE有几十MB,影响产品发布的用户体验。
1.2 常规思维:C/C++比Java快
常规认为:java运行速度比C++慢。主要原因是:
java是解释性语言,java程序在运行时类加载器从类路经中加载相关的类,然后java虚拟机读取该类文件的字节,执行相应操作。而C++编译的时候将程序编译成本地机器码。一般来说java程序执行速度要比C++慢10-30倍。即使采用just-in-time compiling (读取类文件字节后,编译成本地机器码)技术,速度也要比C++慢好多。
java程序有要从网络上加载类字节,然后执行,这也是导致java运行速度慢的原因。
在程序运行过程中,java虚拟机要检测数组是否越界,在C++中则不检测。
java中所有的对象都创建在堆中,没有对象被创建在stack中,而C++有的对象和变量是创建在stack中的
java在运行过程中检测对象的引用是否为空,如果引用指向都空指针,且执行某个方法时会抛出空指针异常
java运行时对类型检测,如果类型不正确会抛出ClassCastException异常。
java的垃圾回收机制较C++由程序员管理内存效率更低。
java中的原始数据类型在每个操作系统平台长度都是相同,而C++这些数据类型长度是随操作系统的不同而不同,所以java在不同操作系统上执行时有个转化过程。
在java中String 是UNICODE.当java要操作一个 ASCII string 时,比C++效率上相对要低一些。
java中采用的是动态链接。
可以看出,这些比较,全部停留在理论的角度。那么实际应用如何呢?是骡子是马,需要拉出来溜溜嘛!
1.3 实际权威测试结果
/642833.html
Java比C++快的理论依据
/1792677.html
驳“.net比java快”的谎言
/1902610.html
C++的速度是由C++编译器在程序员开发时编译出来的机器语言的优化程度决定的。
Java的速度是由Java的JIT和HotSpot编译器将java bytecode在运行时“即时”编译成针对本地CPU的优化的本地代码决定的。
比速度的实际就是在比:看C++编译器和java编译器谁能产生更优化的机器代码。
很明显,C++的编译器不如java的JIT和HotSpot编译器,因为JIT和HotSpot编译器能针对CPU指令集进行人优化、能在运行时根据使用频率对method进行内联和优化。而C++的静态编译器永远也做不到这些。
据IBM研究院的数据显示,随着java技术的进步,java在同样的硬件上的性能从1996年到2001年提高了10倍,而且还在不断提高。
SUN的数据显示:j2se 1.5在各种单项性能上平均比j2se 1.4.2高出10%到30%,而在复杂程序的综合性能上则是j2se1.4的三倍左右。
在丹麦Copenhagen大学的一份长达314页的研究报告中,我们看到:
JDK 1.0时,java的速度是C++的20到40分之一。而到了jdk1.4时,java的性能则是C++的三分之一到2倍(通常C++是java的1.2倍到1.5倍)。在jdk 1.4.2时,java性能全面超过C++。
java在j2se 1.4.2时就已经在性能上全面超过了以c++,以下是几十个权威证据。
美国国家标准科技研究院 12项测试中,java获胜7项,C获胜5项。结论:大多数情况下,java更快;
苹果电脑公司的一份报告:在字符串比较上,Java的性能是C的6.4倍:
美国国家标准科技研究院的另一份报告证明:Java的全面战胜同时代的VC和Borland C;
Java写的数据库的性能是C++写的数据库性能的近600倍!
BGS Systems 公司的三位作者的共同研究报告:我们开始测试是否java程序能够接近C++的性能。但我们吃惊的发现:在client/server应用程序中,java性能优于MFC。
伯克利大学和Lawrence伯克利国家实验室的一份报告证明:IBM的JDK比GCC更快:
用纯java写的JDK底层要比用C++写JDK底层要快:
JNode是一个纯java的操作系统,其jdk底层是用纯java写的。
美国国家标准研究院的一分报告:Java战胜MS VC++ Netbot 联合公司的证据:/javaworld/jw-02-1998/jw-02-jperf_p.html
中: java和C++在以下方面打成平手
Integer division
Dead code with Integer division
Floating-point division
Static method
Member method
Virtual member method
但java在以下方面的速度是C++的约3倍
Virtual member method with down cast and Run-Time Type Identification (RTTI)
http://www.kano.net/javabench/data
14项Benchmark中,Java获胜9项,C++5项 。java以9:5战胜C++,而且其中很多项是以大比分领先:
Methord Call:近20倍
Object creation:4倍
Hash: 2倍半
word count:1倍半
Fibonacci:1倍半
http://cpp.student.utwente.nl/benchmark/
14个Benchmark中
Java-server SUN JDK1.4.2以6比8负于Inter C++8.0
Java-server SUN JDK1.4.2以8比6战胜GCC-i686
Java-server SUN JDK1.4.2以7比7战平GCC-i386
结论:基本战平
但是在此测试中,作者说他“故意”限制了JVM的内存使用量,说这是为了和C++公平。这其实是很不公平的。
java打开-server的目的就是为了“用空间换时间”,在内存中将bytecode编译成更大但是更快的本地码,作者却限制内存使用,
就如同飞机与汽车比速度时给飞机和汽车同样数量的汽油一样,或者在限制飞机的飞行高度为5米以下一样(飞机在燃料不足或低空的情况下是不可能以最快的速度飞行了)
看似公平,实则极不公平,飞机就是靠大量的燃料来加速,不给燃料还比什么呢?如果给飞机和汽车同样多的燃料,飞机每跑100米就要停下来加一次油,怎么可能发挥最快速度呢?
而且,所有的java程序都会比相同算法的c++程序的内存用的多,毕竟JVM就要占去很多内存,如果想比较java和c++的速度,就绝不能要求他们的内存是相同的,就如同想比较飞机和汽车谁快,就绝不能要求他们用的油是相同的。
如果不限制内存使用量的话,相信java会更快。
IBM研究的JVM已经证明了Java即使在数学运算中性能也超过C和Fortran。
Fortran90:Java的结果(单位为秒)
输了的两项是以不到1%的差距输的
而赢了的三项中有两项是以33%以上的差距获胜的
而Java高性能编译器只以2:3的微小差距略负于高性能Fortran(High-Performance Fortran, version 2.2.)
IBM的报告:Servlet与CGI的性能对比: 结论:Servlet性能大大超过用C写的CGI:评测报告:.NET的性能仍然远远落后于Java
麻省理工大学的一位研究员的报告:再来看看用纯java写的MD5算法FastMD5,使用JIT进行native编译后的FastMD5,在linux上处理679,477,248 bytes 大的文件,Java Fast MD5的成绩是34.325秒,而用C写的RedHat linux的textutils-2.0.14-2.i386.rpm用时是59.87667秒。而且,java经过一些设置后,速度还能比前面的更快。英文原文见:/myjava/fast_md5.php
Swing GUI图形界面的性能: 在菜单、树形、文本框、table等几项上,jdk1.4.0比jdk1.3.1快40%到90%。Reflection的性能上,jdk1.4.0比jdk1.3.1快20倍!快20倍以上的还包括远程窗口调用 。其它各项上,jdk1.4.0几乎都比jdk1.3.1快50%以上,“Java慢”也只是“历史”了 。其它各方面的性能提升在此
/j2se/1.4/performance.guide.html
SUN的数据说明,JDK1.4.2在各方面的性能是jdk1.4.1的50%到380% 可以看到,几乎每次java的版本提高都带来性能的极大提升。所以如果你在某处看到一个benchmark说C++比java快,那就很可能是用的老版本的java。 但是C++近年似乎没什么速度的提升
/j2se/1.4.2/1.4.2_whitepaper.html
英国爱丁堡并行计算中心(http://www.ukhec.ac.uk/publications/reports/hpc_java_comp.pdf),由于使用了古老的JDK1.3.1,而且没有打开-server选项运行java,所以不能代表java最高速度。尽管如此,还是能够看到Java的性能非常接近C和Fortran:
在1000000次方法调用(method call)的测试中,Java 1.0的性能竟是C++的171.2%!也就是说:Java在1.0版本时就在"方法调用"这一项上超过了C++!
Dieselpoint公司:JDK 1.3就已能在某些方面超过同时代的VC 6.0 与Borland C:事实上,说“java慢”是错误的。Java已经进化成开发“超级快”的程序的伟大选择!这证明了完全可以用java写出比其它语言(例如c++)更快的程序/pdf/WhitePaper-JavaAndPerformance.pdf
JIT编译器知道什么处理器正在运行,可以产生对应此处理器的优化代码。它知道是否处理器是P3或P4,是否SSE2存在,cache有多大。一个C++之类的预先编译器只能针对所有处理器的指令集的“最小公分母”进行编译,至少在商业软件中是这样的。因为JIT编译器知道哪些类被实际装载和调用,它知道哪些方法可以被“消虚拟化(de-virtualized)” 和内联(值得一提的是:当代java编译器还能知道在被覆盖的方法被装载的情况下,在JIT编译后进行“逆编译”内联的方法调用)。
Java code比C++更快的原因:C++进行的优化是静态优化,都是在编译的时候进行的。一旦编译链接生成的可执行本地代码,就盖棺定论了, 不能更改了,除非是Hacker或是病毒。就现在的编译技术来看,静态优化在总体上还是最成熟的,并且在编译的时候它没有时间压力,可以花很长时间来优化程序。这点Java和.NET是不允许的。但是静态优化也有它的缺点,因为它不知道这些程序在运行的时候具体会有什么特征,无法针对性地进行优化。比如它就不可能“大胆”的进行Method inlining。因为它胆子大了就可能犯错误。比如一个Class A,它有个简单函数public int Foo() {return 3;},它的两个子类B和C Override了这个Foo()函数。那么在静态编译的时候,C++的编译器不能将Foo()这个函数作inlining优化,因为它不知道在运行的时候到底是A,还是B或是C的Foo()被调用。而Java的虚拟机在运行时就会知道这些信息。如果发现运行的时候是B的Foo()在反复被调用,那么它就 大胆的将B的Foo()拿到调用者的程序里面来,这样的inlining处理避免了Function call的开销(仔细说就是No method call;No dynamic dispatch;Possible to constant-fold the value)。对于简单的小函数,调用开销往往比执行还费时间。省略了这些开销性能会成倍的提高。如果这些小函数被上千上万次的调用,那么这样优化下来的效果就非常明显了。这也就是Java在有的时候比C++更快的原因之一。当然,Java做优化实际上相当复杂,因为“大胆”优化有时候也会出现问题。比如 将B的Foo()的inlining了,结果突然的蹦出一个对A的Foo()的调用,那程序岂不是要出问题?这个时候呢,Java要退一步,进行反优化 (De-optimization),以确保程序的正确。就这样,Java的虚拟机“骑着毛驴看账本---走着瞧”。一边执行,一边优化,运行不停,优化不止。从外表上看,Java的程序执行会不停的有小的波 动。我说的动态优化/反优化就是原因之一(还有很多其他原因)。Java这种特性非常适合长时间运行的服务器端程序,因为这样Hotspot才有足够的机会对程序进行优化。如果程序只是简单的“Hello world”,那Hotspot一点忙帮不上。并且对于“Hello world”这么个简单的程序,一个Java VM也要启动,这就像你点着了一台锅炉,只是想煎一个鸡蛋。好多人觉得Java慢,最初的影像可能就是来源于此。
有人这时候一定会问:“既然这样,那为什么Hotspot不对程序就行全盘优化,那样岂不是更好?”。问题是这样的,优化是有代价的。比如一段程序运行要 2毫秒,优化要10毫秒。如果这段程序的执行密度很低,那么Hotspot就会觉得优化不划算而不予优化。你不妨这样想,Hotspot是一个精明的商人,赔本的生意它绝对不会做。
最后再指出一点,那就是Hotspot有客户机和服务器两套(-client, -server),它们有不同的优化方针和策略。
浏览: 298515 次
来自: 北京
jquery瀑布流插件Wookmark完整使用demo - h ...
这篇文章是你写的吗?
you are a great learner!!!}

我要回帖

更多关于 字符指针 字符数组 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信