【基础知识】C++与Java的参数传递
2010-06-29 01:01
253 查看
今天我试着思考一下【参数传递】。
[b]理论基础[/b]
严格上讲,参数传递只有一种方式——值传递(by value)。那么广为流传的参数的两种传递方式:值传递(by value)和地址传递(by address)是怎么一回事呢?
这个问题或许连笨蛋都可以回答,因为仅仅从文字的语义上就可以找到答案,那就是:地址也是一种值。
回答如此简单,简单到足以让人们误以为理解其含义,止步于更深度的探求。懂得思考的人没有放弃继续追根到底的机会:什么是值?什么是地址?既然地址就是值,那么为什么存在值传递与地址传递的对立?
(未完待续,吃饭)
(吃饭回来后,又过了两天...)
什么是值?这个问题或许可以从盘古开天辟地说起,值就是数据,这个空间到处都存在数据。你问什么是数据?额,数据就是数据。但并不是所有的数据都是值。数据就其本身而言不能表示任何事物,是没有任何实际意义的。把‘计算机能够理解’定义为‘计算机可读’,那么值是有‘实际意义’的数据,是计算机可读的,而数据本身是计算机不可读的。因为值是编程语言能够表示的数据,是和类型相关的。比如int类型,struct类型,enum类型等,因此值是类型的值。类型有简单与复杂之分,值也有简单与复杂之别。(经过这番思考,我终于理解了一个概念。以前老是搞不清楚什么叫做‘计算机可读’,原来如果数据有了类型之后就是‘计算机可读’,数据有了类型之后就变成了‘值’,‘值’是计算机可读的。)
什么是地址?地址是相对于计算机内存而言的。计算机内存是一个存储‘数据’的地方。所以,内存和数据具有等价的概念。由于内存存储的是二进制的数据,因此内存最小的组成单位是bit,8个bit为一个最小单元,称为一个字节(byte)。为了便于组织数据,给每个字节赋予一个唯一的地址值,第一个字节为0,第二个字节为1...第n个字节为n。但是即使给每个字节都编了地址,数据依然是杂乱无章,没有任何实际意义。‘数据’通过‘类型’转化为有意义的‘值’。‘类型’好比‘模具’,凡是被框住的‘数据’就加工成了计算机可读的‘值’。值有大小之分,小到一个字节,大到有多个字节。对于有多个字节的值,存在多个地址值,我们规定首字节的地址为‘值’的地址值。
既然地址就是值,那么为什么存在值传递与地址传递的对立? 根本原因在于‘传递’二字,因为值是有大小的,有简单和复杂之分。复杂值的传递肯定比简单值的传递花费更多的代价。地址值顶多是个unsinged int类型的简单值。因此对于复杂类型而言,答案不言而喻。
[b]语言实现[/b]
类型有简单和复杂之分,类型的值也有简单和复杂之别。但是由于两种‘传递’方式的对立,最终衍生出三种类型。
简单类型(build-in): 值传递。
复杂类型(user-defined)有两种: 值类型和引用类型。值类型为值传递,引用类型为地址传递。
对于简单类型,各大主流编程语言处理上是一致的。对于复杂类型(class or struct),C++默认情况下是值类型,Java默认情况下是引用类型,C#两者兼具,struct为值类型,class为引用类型。
C++参数传递
在C++中,默认情况下是以by value方式传递对象到函数,同样也是以by value的方式从函数返回对象(这种方式是从C语言继承来的)。因此,无论是传入或是传出,都要复制并生成原对象(实参)的副本(形参),对副本(形参)的任何更改不会改变原对象(实参)的状态。
对于build-in类型,by value方式仅仅是复制变量的值,由于内置类型存储的数据比较简单,因此复制操作也不会带来大的性能问题。
对于user-defined类型,by value方式会调用对象的copy constructor。当copy constructor比较复杂时,在参数传递过程中就会引起一系列的构造与析构行为,造成性能的下降。为了提高性能,必须避免在参数传递时copy构造函数的调用。这时,按地址传递是比较好的选择。上文提到by value方式操作的仅仅是对象的副本,对副本的任何更改不会改变原有对象的状态。因此,从原对象(实参等)的角度来看,by value方式像一种只读行为,因为by value方式不会改变原对象的状态。因此为了更好的模拟by value的方式,在用地址传递代替值传递时,最好加上const关键字。
C++中有两种按地址传递的方式:pass-by-reference-to-const和pass-by-pointer-to-const。
pass-by-reference-to-const:
上述两种传递方式在汇编级别和二进制级别的代码上是相同的。
待续。。
[b]理论基础[/b]
严格上讲,参数传递只有一种方式——值传递(by value)。那么广为流传的参数的两种传递方式:值传递(by value)和地址传递(by address)是怎么一回事呢?
这个问题或许连笨蛋都可以回答,因为仅仅从文字的语义上就可以找到答案,那就是:地址也是一种值。
回答如此简单,简单到足以让人们误以为理解其含义,止步于更深度的探求。懂得思考的人没有放弃继续追根到底的机会:什么是值?什么是地址?既然地址就是值,那么为什么存在值传递与地址传递的对立?
(未完待续,吃饭)
(吃饭回来后,又过了两天...)
什么是值?这个问题或许可以从盘古开天辟地说起,值就是数据,这个空间到处都存在数据。你问什么是数据?额,数据就是数据。但并不是所有的数据都是值。数据就其本身而言不能表示任何事物,是没有任何实际意义的。把‘计算机能够理解’定义为‘计算机可读’,那么值是有‘实际意义’的数据,是计算机可读的,而数据本身是计算机不可读的。因为值是编程语言能够表示的数据,是和类型相关的。比如int类型,struct类型,enum类型等,因此值是类型的值。类型有简单与复杂之分,值也有简单与复杂之别。(经过这番思考,我终于理解了一个概念。以前老是搞不清楚什么叫做‘计算机可读’,原来如果数据有了类型之后就是‘计算机可读’,数据有了类型之后就变成了‘值’,‘值’是计算机可读的。)
什么是地址?地址是相对于计算机内存而言的。计算机内存是一个存储‘数据’的地方。所以,内存和数据具有等价的概念。由于内存存储的是二进制的数据,因此内存最小的组成单位是bit,8个bit为一个最小单元,称为一个字节(byte)。为了便于组织数据,给每个字节赋予一个唯一的地址值,第一个字节为0,第二个字节为1...第n个字节为n。但是即使给每个字节都编了地址,数据依然是杂乱无章,没有任何实际意义。‘数据’通过‘类型’转化为有意义的‘值’。‘类型’好比‘模具’,凡是被框住的‘数据’就加工成了计算机可读的‘值’。值有大小之分,小到一个字节,大到有多个字节。对于有多个字节的值,存在多个地址值,我们规定首字节的地址为‘值’的地址值。
既然地址就是值,那么为什么存在值传递与地址传递的对立? 根本原因在于‘传递’二字,因为值是有大小的,有简单和复杂之分。复杂值的传递肯定比简单值的传递花费更多的代价。地址值顶多是个unsinged int类型的简单值。因此对于复杂类型而言,答案不言而喻。
[b]语言实现[/b]
类型有简单和复杂之分,类型的值也有简单和复杂之别。但是由于两种‘传递’方式的对立,最终衍生出三种类型。
简单类型(build-in): 值传递。
复杂类型(user-defined)有两种: 值类型和引用类型。值类型为值传递,引用类型为地址传递。
对于简单类型,各大主流编程语言处理上是一致的。对于复杂类型(class or struct),C++默认情况下是值类型,Java默认情况下是引用类型,C#两者兼具,struct为值类型,class为引用类型。
C++参数传递
在C++中,默认情况下是以by value方式传递对象到函数,同样也是以by value的方式从函数返回对象(这种方式是从C语言继承来的)。因此,无论是传入或是传出,都要复制并生成原对象(实参)的副本(形参),对副本(形参)的任何更改不会改变原对象(实参)的状态。
对于build-in类型,by value方式仅仅是复制变量的值,由于内置类型存储的数据比较简单,因此复制操作也不会带来大的性能问题。
对于user-defined类型,by value方式会调用对象的copy constructor。当copy constructor比较复杂时,在参数传递过程中就会引起一系列的构造与析构行为,造成性能的下降。为了提高性能,必须避免在参数传递时copy构造函数的调用。这时,按地址传递是比较好的选择。上文提到by value方式操作的仅仅是对象的副本,对副本的任何更改不会改变原有对象的状态。因此,从原对象(实参等)的角度来看,by value方式像一种只读行为,因为by value方式不会改变原对象的状态。因此为了更好的模拟by value的方式,在用地址传递代替值传递时,最好加上const关键字。
C++中有两种按地址传递的方式:pass-by-reference-to-const和pass-by-pointer-to-const。
pass-by-reference-to-const:
pass-by-pointer-to-const:[/b] void getAnimalName(const Animal* ani){ cout << ani->getName() << endl; }
上述两种传递方式在汇编级别和二进制级别的代码上是相同的。
待续。。
相关文章推荐
- 【java基础知识(学习笔记)】--方法中的参数传递
- JAVA基础知识回顾之---方法中的参数传递
- [C\C++基础知识] main函数的参数argc和argv
- [C\C++基础知识] main函数的参数argc和argv
- C++与java中的参数传递
- 函数的参数传递的几种形式(值、地址、引用)及指针基础知识
- c/c++/java,函数调用的参数的传递方法
- Java_语法基础_注意方法中传递的参数要求
- C++三种参数传递方法(值传递、指针传递、引用传递)的一些知识
- Java基础知识---数组的引用传递
- 14.Java 基础 - 参数传递
- Java基础:参数传递(一)
- C++基础---函数的参数传递
- 编程基础知识——C++能不能支持Java和ObjC的反射?
- Jni 参数传递与操作——(C/C++ 代码与 java 代码的互相调用)
- 编程语言基础:用“收集器”理解各种语言(C++、Java、Python)中的可变参数!
- JNI+opencv3+.dll+eclipse+vs2015:java调用c++传递String类型参数全过程
- Java基础之参数传递
- 【PHP】PHP基础知识与C++、Java等C家族的重点区别
- Java和C++中的参数传递