At work today, I wrote the code happily.
A colleague ran over excitedly and said, "ah yuan, look at your enterprise wechat.".
Me: "what's the situation? Do you want a raise?"
Colleague: "will salary increase be said on enterprise wechat?"
Me: "Okay"
When I opened enterprise wechat, it turned out to be an interview question, -# - #.
#include <iostream> using namespace std; class Persion{ public: void doWork(){ cout<<"Do you think I'll collapse?"<<endl; } }; int main(){ Persion *ptr =nullptr; ptr->doWork(); // Will the execution run out here? Guess, guess, guess again? return 0; }
My first intuition: it's bound to collapse. It's all empty pointers. How can it not collapse, but you're good! You're fine!! Will my colleagues ask me such a simple question?
I replied solemnly, "no!!".
Colleague: "do you know why?"
My heart: ten thousand divine beasts are jumping!, Why do men bother men?
"Well, well... I still have a lot to do. You can play."
Finally fooled my colleagues away. Baidu immediately, I see.
Principle analysis
First, we need to know whether the function of a class belongs to a class or an object. The function of class belongs to class, that is, it is a fixed address, rather than dynamically generating a new address every time.
g++ -g test.cpp -o test #Compile debug mode gdb test # gdb debugging
The source code is as follows:
Break the point and run the diagram
disassemble
You can see whether the function he calls is person:: dowork(), which is very similar to the static function call.
The main function, assembly code analysis and summary class function call actually has a hidden parameter, which is the this pointer.
Dump of assembler code for function main(): push %rbp mov %rsp,%rbp sub $0x10,%rsp movq $0x0,-0x8(%rbp) # The assignment pointer is null. mov -0x8(%rbp),%rax # The beginning of the calling function. Use register rax to save the pointer address----- Start----- mov %rax,%rdi # rdi register is used to save function parameters. In fact, it is to pass this pointer to the function as a function parameter. callq 0x4011e8 <Persion::doWork()> # Call function ------ End----- mov $0x0,%eax # return 0 leaveq retq End of assembler dump.
note: the rdi register is used to hold parameters
dowork(), assembly code analysis, we can see that there is no assignment to rax in dowork, so there is no problem.
Dump of assembler code for function Persion::doWork(): 0x00000000004011e8 <+0>: push %rbp 0x00000000004011e9 <+1>: mov %rsp,%rbp 0x00000000004011ec <+4>: sub $0x10,%rsp 0x00000000004011f0 <+8>: mov %rdi,-0x8(%rbp) => 0x00000000004011f4 <+12>: mov $0x402005,%esi 0x00000000004011f9 <+17>: mov $0x404060,%edi 0x00000000004011fe <+22>: callq 0x401050 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt> 0x0000000000401203 <+27>: mov $0x401030,%esi 0x0000000000401208 <+32>: mov %rax,%rdi 0x000000000040120b <+35>: callq 0x401060 <_ZNSolsEPFRSoS_E@plt> 0x0000000000401210 <+40>: nop 0x0000000000401211 <+41>: leaveq 0x0000000000401212 <+42>: retq End of assembler dump.
Run down test
If you change the code to:
#include <iostream> using namespace std; class Persion{ public: int a = 0; void doWork(){ cout<<"Do you think I'll collapse?"<<endl; } }; int main(){ Persion *ptr =nullptr; ptr->doWork(); // Will the execution run out here? Guess, guess, guess again? ptr->a = 10; return 0; }
When using the pointer PTR - > A, it will crash because the null pointer cannot get the address.
summary
Do you think the people who answer this interview question eat too many walnuts pinched by the door? In fact, this problem occurred in my real project. A novice really didn't have new when using the pointer. Due to the logic problem, his this pointer will be called in a specific situation. It also took a lot of time to find the problem, and finally found the reason.
- Class hides the passing of a this pointer.
- Class is used to hold the variables of the object.
- The function of a class belongs to a class, not an object, that is, each object uses the same function.
Ha ha, did you learn??