各语言对象和变量的关系

变量和对象

任何语言都是由变量和对象组成的。

变量和对象可能是存在一块的(变量代表内存,内存存放的的是对象二进制),也可能是分开存的,这种情况就是对象存放在其他内存,而变量存放的是那块内存的地址。

具体方式在不同语言中有很大区别,不同语言在底层可能做了很多优化,例如JVM的栈变量共享等。

1
2
int a = 3;
int b = 3;

对于上述代码,C++的话就是分配了两个值类型变量在不同栈空间,同时分配2个对,内存各自写3。

而对于java,也是分配了两个值类型变量在不同栈空间,但是对象3却是在栈空间单独存在的,值类型变量都是指向这个对象3,虽说是值类型,但是存放的也是地址。但是依然是值类型,有点像python的不可变对象传递。

image-20210121194155398

变量类型

在各种语言中,变量一般分为值类型和引用类型。

值类型

变量直接存放对象的二进制数据(JVM的栈变量共享除外),如果对变量取地址,那么就是这段内存的地址名,例如”0xc00001c100”。

这里的内存空间一般是栈空间,变量和对象都是在栈空间的。

引用类型

引用类型的变量存放的是对象的地址,变量位于栈空间,而对象则是位于堆空间。例如a是引用变量,其内容是”0x12335423341“,这段地址是堆空间的地址,指向堆空间的对象,而自己的地址可能是”0x51314241“,是在栈空间的地址。

引用类型有个巨大的好处是自动垃圾回收GC,通过引用计数可以释放没有引用的对象。

不同语言总结

  • Java:

    • 值类型:基本数据类型int/float/short/long/double/byte/char/bool
    • 引用类型:其余全是
  • Python

    • 全是引用类型,python的对象基本是heap空间
  • Go:

    • 值类型:基本数据类型int, float,bool, string,以及数组和struct
    • 引用类型:其余全是,Go存在指针
  • C++:

    • 全是值类型
    • 引用类型:通过指针,引用&,shared_ptr等实现。

栈空间堆空间

正如前文所说,栈空间一般是值类型的对象和变量空间,堆空间是引用变量的对象空间,堆空间一般都是new或malloc出来的,在C++中需要进行手动创建和释放,程序结束也不一定可以正确释放,容易造成内存泄漏(所以后面有类似java的shared_ptr,做引用计数的垃圾回收)。

除栈空间和堆空间,一般还有

  • 静态空间:存放全局变量、static变量,在程序结束会自动释放
  • 常量空间:类似java的string类型,final修饰的变量
  • 代码空间:存放程序代码

java

  • 对象分为基本数据类型和其他对象,同理变量也就分为基本数据类型的变量和引用变量
  • 基本数据类型的变量操作,产生新的对象,不再指向同一个对象。变量传递相当于对象值传递。
1
例子:int a = 3;int b;b = a; // 两个变量指向同一个栈对象a = 30; // a指向新的栈对象,b=3不会变
  • 引用变量操作,还是指向同一个对象,类似C/C++的指针/引用。变量操作相当于对象地址传递。
1
例子:Class a = new Class();Class b = new Class();b = a; // 两个变量指向同一个堆对象a.set(something); // a,b两个引用变量依然指向同一个堆对象
  • 基本类型的变量和对象,引用变量都放在栈中,引用对象放在堆中。
  • 栈空间的数据对象是共享的,但是堆空间是不共享的。
1
int a = 3; int b = 3; //这个时候3的栈对象已经存在,共享, a == b

python

  • 对象分为可变对象和不可变对象,同理变量也就分为不可变对象的变量和可变对象的变量
  • 不可变对象(整型、字符串和元组)的变量操作,产生新的对象,不再指向同一个对象。变量传递相当于对象值传递。
1
例子:a = 3; b = a; // 两个变量指向同一个对象a = 30; // a指向新的对象,b=3不会变
  • 可变对象的变量操作,还是指向同一个对象,类似C/C++的指针/引用。变量操作相当于对象地址传递。
1
例子:a = Class();b = a; // 两个变量指向同一个对象a.set(something); // a,b两个变量依然指向同一个对象

C/C++

  • 变量有变量的值和地址,对象有对象的值和地址
  • 通过指针来实现对同一个对象的操作,指针的自由度更高,但是代码上相比java和python就更加复杂了,引用变量多方便啊。。
  • C/C++也有指针的高级封装-引用!
1
int a =4 ; int &b = a; b=3 //a = b = 3
  • 即使是基本数据类型,也可以操作为同一个对象
1
int a = 3;int* p = &a;a = 4; // *p和a指向同一个对象

各语言对象和变量的关系
http://yoursite.com/2020/01/07/编程开发/各语言对象和变量的关系/
作者
Wei Lyu
发布于
2020年1月7日
许可协议