There is only one function, so the question doesn't arise like that, but there are many questions about the method, so I'm asking you this question.
A method is declared only once, like Function, but in the process of creating an instance, it seems that several objects are created, and different methods are also created for each object.
Simply put, it's the same code after all, rather than dividing the same code into multiple memory regions. Like StackFrame, I don't think it's necessary to have multiple methods if you take Format so that the method can work as a method (you can use keywords like self and this).
In fact, how are the methods implemented in C++, Java, Javascript, and Python? Is it just that each code goes up in the memory area every time an instance is created?
In the case of Python, it just seemed to create one method for each object.
Do static languages like C++ and Java bring together methods and share routines using devices like Stackframe?
programming-language
I don't know much about javascript, but it will be similar to other languages.
For the method (non-static member function) you mentioned, there is only one memory with a function code, as is a common function. Methods are not created per instance.
Of course, this is not said to be the case in the standard, but in most implementations, the code of the method has the same location because it is a part of the language implementation that can be processed without allocating the method by instance.
Then, depending on the instance of the class, the method is how it works, which is implemented to allow the function to use the self or this keyword. When a member variable (field) is accessed within the method, the compiler creates the method so that the member variable can be accessed from this without using this.
If you take C++ as an example, you have the following classes:
class Test {
int a;
public:
void test() {
a = 1;
}
};
int main() {
Test t;
t.test();
}
If you look at the x86-64 assembly in test()
here:
Test::test():
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
mov rax, QWORD PTR [rbp-8]
mov DWORD PTR [rax], 1
nop
pop rbp
ret
main:
push rbp
mov rbp, rsp
sub rsp, 16
lea rax, [rbp-4]
mov rdi, rax
call Test::test()
mov eax, 0
leave
ret
In the assembly, the method test()
is in a fixed position and is not newly created per instance.
There are the following parts of the contents.
lea rax, [rbp-4]
mov rdi, rax
call Test::test()
Save the address of the instance in rdi
before calling test()
.
In other words, the rdi
register has the meaning of this
.
Next, if you look at the test()
internal code, it is shown below.
mov QWORD PTR [rbp-8], rdi
mov rax, QWORD PTR [rbp-8]
mov DWORD PTR [rax], 1
rdi
Reads the address from the register and stores the value 1
at the address.
The first C++ code set 1 for the variable a
and the above assembly sets 1 for the address of rdi
.
Since there is a variable a
at the beginning of Test
, this
will eventually become the address of a
.
In other words, in the implementation of C++, the method exists by class, not by instance, and this
is passed in the calling phase to access the instance within the method.
In C++, the method is usually implemented in such a way that this
has the first invisible parameter and is stored there.
Python clearly shows how it will behave when defining methods in the language itself.
class Test:
def __init__(self):
self.a = 0
def test(self):
self.a = 1
t = Test()
t.test()
When defining a method in Python, self
is added as the first parameter.
When calling the method, do not put a separate factor for the self
parameter as shown above.
This is put in by the interpreter at the calling stage.
At the linguistic level, you receive an instance through parameters, and you don't need to create a method for each instance, and so is the implementation.
Think about Java.
class Test {
private int a;
public void test() {
a = 1;
}
public static void main() {
Test t = new Test();
t.test();
}
}
The byte code of the above code is as follows.
class Test {
<ClassVersion=52>
<SourceFile=OtherClass.java>
private int a;
Test() { // <init> //()V
L1 {
aload0 // reference to self
invokespecial java/lang/Object.<init>()V
return
}
}
public test() { //()V
L1 {
aload0 // reference to self
iconst_1
putfield Test.a:int
}
L2 {
return
}
}
public static main() { //()V
L1 {
new Test
dup
invokespecial Test.<init>()V
astore0
}
L2 {
aload0
invokevirtual Test.test()V
}
L3 {
return
}
}
}
The code calling test()
is shown below.
aload0
invokevirtual Test.test()V
aload0
places the value of the region variable 0 in the stack.
This is the process of entering the call factor for test()
, and the region variable 0 will be Test
.
Invoke Test.test()
via invokevirtual
.
public test() { //()V
L1 {
aload0 // reference to self
iconst_1
putfield Test.a:int
}
L2 {
return
}
}
In test()
, aload0
is the command to put the local variable 0 in the stack.
However, although there is no region variable in the actual Java code, the value accumulated in the stack in invokevirtual
becomes the region variable.
Although invisible, this
is passed through the parameters.
That is, Java also forwards the address of the instance through the stack, not generating the method per instance.
Of course, not all language or language implementations may work this way. However, in most cases, the method exists in one place, and the separation of instances is accessed through invisible parameters.
JavaScript has a primitive object When you create an instance with the new keyword, it is connected to the raw object to look at a predefined function. This is called a prototype chain, and it will not be different from the basic aspects of other languages in memory usage of memory.
However, JavaScript is a first-class citizen object and can express high-level functions, so depending on what code you write, a function that goes up to the memory area every time you instantiate the class. (But isn't it the same in other languages?) I don't know this well either.)
JavaScript is not a static language, so this
is not interpreted at compile time.
this
is defined in the execution time. Each instance passes its own context to the prototype method at runtime to confirm this
. Looking at this case, it's not much different from the first answer you gave me above.
© 2024 OneMinuteCode. All rights reserved.