l值和r值,堆栈和堆

时间:2017-02-16 15:16:07

标签: java

我是一名学习Java的高中生(在BlueJ环境中)。

上下文

我的书在讨论按值传递并通过引用机制传递时,使用术语,堆栈和堆,并且还指出内存中的每个单元(也称为变量)都具有名称 l-value r-value ,其中 l 代表'locator'或'location', r 代表'读'。该名称用于标识单位,l值存储单位的地址,r值存储单位的实际值。在原始数据类型的情况下,它存储实际值,而在引用数据类型的情况下,它存储引用或指向它的引用数据类型的地址。调用带参数的函数时,实际参数的r值将复制到实际参数的r值中。在原始数据类型的情况下,复制实际值,而在参考数据类型的情况下,复制参考地址,因为在前一种情况下实际值没有变化,而在后一种情况下实际值有变化。

我的问题

现在,我决定在互联网上了解更多相关信息。我发现互联网上的讨论与我的书不一致。 l值和r值分别被认为是分配符号的左手侧和右手侧的值。我很迷惑。

l值和r值的实际含义是什么?我的书的意思是堆栈,堆(我想要一个简单易懂的答案)和内存单元。我在这个网站上发现了许多关于堆栈和堆的问题,但由于它们非常技术性而无法理解那里的答案,因此我没有太多的技术知识。此外,我想知道我可以在哪里了解更多关于这个

以下是我教科书中的页面:

enter image description here

enter image description here

enter image description here enter image description here

2 个答案:

答案 0 :(得分:5)

  1. 首次创造条款l-valuer-value时,l和r 确实意味着左右。也就是说,l值最初意味着左 分配的手边和r值意味着右手边 分配。然而,在稍后,他们被修改以表明 '定位器'并且'阅读'分别如你的书所示。原因 是像C这样的编程语言有很多运算符(例如 运算符的地址&)其中右侧显示的操作数 运营商的手边仍是l值。
  2. stackheap是记忆中的区域。堆栈用于存储 局部变量和函数调用。堆用于存储objects。 堆叠时,堆由应用程序的所有线程共享 分配给每个帖子。

答案 1 :(得分:2)

堆叠和堆:

堆栈

堆栈只是每个程序开始的特定内存范围。每个程序都有一个堆栈,当编程运行时,CPU实际上存储了一个指针,指向堆栈的“顶部”。 调用函数时,代码(由编译器生成)将值(参数的副本以及调用函数的代码的返回地址)写入内存中由此堆栈指针(SP)引用的点。然后它会修改SP,使其更进一步指向参数之后的点。

当函数返回时,它将返回值写入SP指向的内存中的点,然后将代码执行跳转回调用该函数的代码。然后该代码从SP位置复制返回值,并递减SP。

这个区域被称为堆栈,因为当你声明局部变量时,程序会将值复制到它上面。或者你用参数调用函数。
然后,当从函数返回时,它会“弹出”参数和局部变量。

(这就是它在理论上的工作原理。实际上,编译器会编写指令来将值复制到CPU寄存器,而不是它可以。还有返回值。)

堆简单地引用程序分配的所有其他内存,通常是系统调用(linux中的brk)(在C中由malloc调用)。程序可以有许多内存块,它要求操作系统分配给它。这些内存块(作为一个整体)称为堆。

在java中:

  • 当你使用'new'关键字时,它的作用是返回一个指向某个内存的指针,它要求操作系统提供它。

  • 当你声明一个不使用new的变量时,编译代码会做的只是使用堆栈内存区域顶部的现有内存,然后更改堆栈指针。

当你使用指针变量并为它指定一个用新的ExampleObject()创建的对象时,你实际上正在做这两件事。在这种情况下,指针(引用)变量将在堆栈指针位置创建。然后移动堆栈指针(添加到8个字节,指针值的大小),然后new()函数将从堆区域获取新的内存引用,然后该引用的值将被复制到本地指针变量。

在实践中,像Java这样的语言在执行程序时,以一定大小的堆栈开始,并且操作系统已经为它分配了一定大小的内存(称为堆),并且只有在需要时才会要求更多的内存。耗尽空间

值得您花些时间阅读CPU的工作原理,特别是它们如何存储存储值的寄存器,其中一个是堆栈指针。他们如何执行加法和减法。这很重要,因为它们(通常)不会(例如)在添加时,将内存中引用地址的数字添加到另一个引用地址中的数字。如果你看看汇编指令(类似于java字节代码)他们更常做的事情更像是:

例如函数int addnum(int a,int b){return a + b;}   一个。将SP中的数字(即SP指向的位置)加载到寄存器1

湾从SP指向(SP-1)之前加载数字到寄存器2

℃。调用Add CPU指令,将结果存储在寄存器R3中   d。将R3值复制到SP + 1

可能看起来像

调用这样的代码:(注意,这些是由CPU指令组成的示例 - 它们对于每个CPU都是不同的,Java有自己的字节码,类似。我只是使用例如STORESP =>写入堆栈, LOADSP =>从堆栈指针加载

int x;
x =  addnum(9,6);

INCSP  +1   #allocate x at location SP and increment SP by 1

# start function call
# make 3 spaces,   for a, b, and b and return value
INCSP   +3       #add 3 to SP register
STORESP 9,0           # copy 9 value  to SP-0
STORESP 6,-1         # copy 6 value  to SP-1

JUMP addnum    # jump to executing the function code                

然后,函数本身

LOADSP,0,R1       #copy from SP-0 (a) into reg 1
LOADSP,-1,R2     #copy from SP-1(b) into reg 2
ADDREG,R1,R2,R3 # add reg1 reg2 and store in R3

STORESP,R3,-2        #save the result to SP-2
RETURN

然后再次调用函数: 将结果存储在x(复制SP-2)(到SP-3)

LOADSP,-2,R1
STORESP,R1,-3

现在函数调用已完成。因此,抛弃堆栈上为a和b分配的空间以及返回值 (通过将SP递减3)

ADDSP -3

现在结果是'x'

当然这很简单,也不准确,但只是为了帮助理解。

但是如果你可以看看这些低级别的东西是如何工作的,只是做一些基本的事情,比如添加两个数字,那么它将帮助你理解“where”和“how”参数在函数中传递,以及确切的重要性堆栈概念是

祝你好运