我是一名学习Java的高中生(在BlueJ环境中)。
上下文
我的书在讨论按值传递并通过引用机制传递时,使用术语,堆栈和堆,并且还指出内存中的每个单元(也称为变量)都具有名称, l-value 和 r-value ,其中 l 代表'locator'或'location', r 代表'读'。该名称用于标识单位,l值存储单位的地址,r值存储单位的实际值。在原始数据类型的情况下,它存储实际值,而在引用数据类型的情况下,它存储引用或指向它的引用数据类型的地址。调用带参数的函数时,实际参数的r值将复制到实际参数的r值中。在原始数据类型的情况下,复制实际值,而在参考数据类型的情况下,复制参考地址,因为在前一种情况下实际值没有变化,而在后一种情况下实际值有变化。
我的问题
现在,我决定在互联网上了解更多相关信息。我发现互联网上的讨论与我的书不一致。 l值和r值分别被认为是分配符号的左手侧和右手侧的值。我很迷惑。
l值和r值的实际含义是什么?我的书的意思是堆栈,堆(我想要一个简单易懂的答案)和内存单元。我在这个网站上发现了许多关于堆栈和堆的问题,但由于它们非常技术性而无法理解那里的答案,因此我没有太多的技术知识。此外,我想知道我可以在哪里了解更多关于这个
以下是我教科书中的页面:
答案 0 :(得分:5)
l-value
和r-value
时,l和r
确实意味着左右。也就是说,l值最初意味着左
分配的手边和r值意味着右手边
分配。然而,在稍后,他们被修改以表明
'定位器'并且'阅读'分别如你的书所示。原因
是像C这样的编程语言有很多运算符(例如
运算符的地址&
)其中右侧显示的操作数
运营商的手边仍是l值。stack
和heap
是记忆中的区域。堆栈用于存储
局部变量和函数调用。堆用于存储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”参数在函数中传递,以及确切的重要性堆栈概念是
祝你好运