类型比较
数据类型可以看做两种:值类型和引用类型,由于他们类型不同,在不同的语言中对他们的处理方式也不一样,在其整个生命周期当中它们表现出不同的生命迹象。
1. C#
类型分类:
A.值类型:
数值型(byte,unsigned byte,short,unsigned short, int,unsigned int,long,unsigned long,float,double,decimal)字符型(char)结构体(struct)枚举(enum)
B.引用类型:
类(class),委托(delegate),事件(event),接口(interface)以及其他的非基本类型的数据结构。
表现行为:
A. 单纯的值类型的数据产生时,将会在运行栈上分配内存,具体大小因不同的数据类型和系统平台而不同,eg(int类型在xp、03等32位平台上会有4bytes的内存空间,long类型有8bytes的空间)
引用类型的创建发生在托管堆上,当我们声明className varname;时,首先会在堆栈上创建一个引用,只有当出现varname=new className();的时候,才会真正的在托管堆上分配内存空间,对于c#来说,一个对象的内存空间不仅仅时该对象所包含数据的大小的对应加和,每个对象含有额外的指针,大小分别位4bytes,例如method table的指针,以及同步指针等。
B. 当值类型的数据作为参数传递到方法中时,在内存中会产生该数据的copy,也就是说,进行值传递时,我们是对数据的复本进行操作,它的改变不影响原来数据的值。
当我们把引用类型作为参数进行传递时,其实我们传递的是对象的指针,它只是会在栈上重新创建一个指针对象,当我们对这个指针对象进行操作时,所有的改变都将影响到原对象。
C. 当一个引用对象中含有值类型的字段的时候,其内部的值类型的字段的空间也是分配在托管堆上的。
D. String类型是一个特殊的引用类型,其原因时为了提高String类型的操作效率,编译器对string类型进行了优化。具体为:
String a=”this is first string !”;
String b=”this is second string !”;
String c=”this is first stirng !”;
当我们执行以上三条语句的时候,内存中其实只有两个字符串的值,也就是说a和c指向内存同一个地方,而当他们其中一个发生改变的时候,另一个的值并不会发生改变。这就是字符串驻留机制的结果。
String a=”a”;
String b=”b”;
Sting c=”ab”;
String d=”a”+”b”;
此时d和c同样是指向内存中同一块地址的,也就是说当某个字符串已经存在后,如果再有其他字符串变量,哪怕是这个变量是通过简单的字符串运算(字符串直接相加)得来的,那么他首先会在系统中的字符串表中寻找,如果这个字符串表存在该字符串那么就是分配个指针,否则分配内存。
E.当需要把值类型按照引用传递时,需要在类型前加ref或者out关键字;在调用方和被调用方该关键字都是必须的。Ref标记的关键字在进行传递之前必须进行初始化,out关键字在传出之前需要进行赋值操作。
2.Java
类型分类:
A.值类型:
数值类型(byte、short、int、long、float、double)字符类型(char)布尔类型(boolean)
B.引用类型:
类,接口,数组等除了8种基本类型之外的类型
表现行为:
A.----D.与C#基本相同
值与引用传递行为与c#同;eg:
class TestData
{
public int a=4;
}
class Change{
public void changeInt(int a)
{
a=5;
}
public void changeRef(TestData td)
{
td.a=90;
}
}
class PersonJ
{
public static void main(String argsp[])
{
TestData td=new TestData();
Change ch=new Change();
int a=3;
System.out.println(a);
//值传递
ch.changeInt(a);
System.out.println(a);
System.out.println(td.a);
//引用传递
ch.changeRef(td);
System.out.println(td.a);
}
}
D表现行为示范,与C#同;eg:
class PersonJ
{
public static void main(String argsp[])
{
String a="abc";
String b="abcd";
String c="abc";
String d=a+"d";d与b的内容虽相同却处于内存中的不同位置
String e=a+b;
String f=a+a+d;f与e随内容相同内存地址却不同
String g="ab"+"cd";g与b内容相同内存地址也相同
System.out.println(a+b+c);
}
}
3.C++
数据分类:
A.C++中所有的数据类型均为值类型:
Short、int、long、float、double、bool、char、struct、union、class等
表现行为:
A.所有的对象传递方式为按值传递方式,除非对参数加修饰关键字*和&;eg
#include <iostream.h>
class Person
{
private:
int age;
public:
void SetAge(int age){Person::age=age;}
int GetAge()const;
};
int inline Person::GetAge() const
{
return age;
}
void change(int a)
{
a=3;
}
void change(int* a)
{
*a=5;
}
void change(Person* p)
{
p->SetAge(25);
}
void change(Person p)
{
p.SetAge(111);
}
int main()
{
Person p,q;
p.SetAge(12);
cout<<"p is "<<p.GetAge()<<endl;
q=p;
cout<<"q is "<<q.GetAge()<<endl;
cout<<"p is "<<p.GetAge()<<endl;
change(q);
cout<<"p is "<<p.GetAge()<<endl;
cout<<"q is "<<q.GetAge()<<endl;
change(&q);
cout<<"p is "<<p.GetAge()<<endl;
cout<<"q is "<<q.GetAge()<<endl;
int x=4;
cout<<"x is "<<x<<endl;
change(x);
cout<<"x is "<<x<<endl;
change(&x);
cout<<"x is "<<x<<endl;
int c;
cin>>c;
return 0;
}
注意:
C++中类对象在向继承层次更高的类型传递时有切割问题存在。Eg
#include <iostream.h>
class Person
{
public:
virtual void SetAge(){cout<<"Base class"<<endl;}
};
class Man:public Person
{
public:
void SetAge(){cout<<"Child class"<<endl;}
};
void Dest(Person m)/*传子类造成子类特性的切除*/
{
m.SetAge();
}
void Seco(Person* m)/*不会造成特性切除的传递方式*/
{
m->SetAge();
}
void Thir(Person& m)
{
m.SetAge();
}
int main()
{
Man m;
Person p;
Dest(m);
Dest(p);
Seco(&p);
Seco(&m);
Thir(p);
Thir(m);
int c;
cin>>c;
return 0;
}
原创文章,转载请注明出处!
All CopyRight Reserved !
主页:http://jingtao.cnblogs.com
QQ:307073463
Email:jingtaodeemail@qq.com
MSN:sunjingtao@live.com
本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名孙镜涛(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言。