Why is the function pointer in C + + 16 bytes

Source: Internet
Author: User

Original link

When we talk about pointers, it is often assumed that it is something that can be represented by a void * pointer, which x86_64 is 8 bytes in size under a platform. For example, here is an excerpt from the x86_64 article on Wikipedia:

Pushes and pops on the stack are always in 8-byte strides, and pointers are 8 bytes wide.

From CPU the point of view, the pointer is nothing more than the memory address, all the memory address x86_64 under the platform is represented by 64 bits, so assume that it is 8 bytes is correct. It is not difficult to verify what we say by simply outputting the lengths of different types of pointers.

#include <iostream>int main() {    std::cout <<        "sizeof(int*)      == "sizeof(int"\n"        "sizeof(double*)   == "sizeof(double"\n"        "sizeof(void(*)()) == "sizeof(voidstd::endl;}

Compile and run the above program, from the results can be seen all the length of the pointer is 8 bytes:

$ uname -ix86_64$ g++ -Wall ./example.cc$ ./a.outsizeof(int*)      8sizeof(double*)   8sizeof(void8

There is, however, a C++ special case-a pointer to the member function . It's interesting, the member function pointer is twice times the length of any other pointer . This can be verified by the following simple program, the result of the output is 16 :

#include <iostream>struct Foo {    voidconst { }};int main() {    std::coutsizeofstd::endl;}

Does this mean that Wikipedia is wrong? Obviously not! From a hardware point of view, all pointers are still 8 bytes. So, what is the pointer to the member function? This is a C++ language feature, where pointers to member functions are not mapped directly to hardware, and are implemented by the runtime (compiler), which can incur some additional overhead, often resulting in a loss of performance. The C++ language specification does not refer to the implementation details, nor does it explain this type of pointer. Fortunately, the Itanium C++ ABI specification shares the C++ details of the runtime implementation--for example, it explains Virtual Table RTTI how, and how the exception is implemented, and §2.3 also explains the member pointers:

A pointer toMemberfunction  isA pair asFollows:ptr: forA non-virtualfunction, this field isA simplefunctionPointer. forA virtualfunction, it is 1Plus the virtual table offset (inchbytes ofThefunction, represented asA ptrdiff_t. The value zero represents a NULL pointer, Independent ofThe adjustment field value below.adj:The required adjustment toThis, represented asA ptrdiff_t.

Therefore, a member pointer is a 16 byte 8 , not a byte, because after a simple function pointer you also need to save information about how to adjust this the pointer (which is always passed implicitly to the non-static member function). The ABI specification does not say why and when the pointer needs to be adjusted this . It may not be obvious at first, let's look at the following examples of class inheritance:

struct  A {void  foo () const  {} char  Pad0[32 ];}; struct  B {void  Bar () const  {} char  pad2[64 ];}; struct  C:a, b{};  

AAnd B both have a non-static member function and a data member. These two methods can be used to access this data members in their classes by implicitly passing pointers to them. To access any data member, you need to this add an offset to the pointer, which is the offset of the data member to the base address of the class object , which can be ptrdiff_t represented by. However, things will become more complex in multiple succession. We have a class C A that inherits and B , what will happen? The compiler puts A and B puts the values of the pointers in memory, B A below, so that the methods of the A class and B the methods of the class see a different this value. This can be verified by practice, such as:

#include <iostream>structAvoidFoo ()Const{STD::cout<<"A ' s This:"<< This<<STD:: Endl; }Charpad0[ +];};structb{voidBar ()Const{STD::cout<<"B ' s This:"<< This<<STD:: Endl; }Charpad2[ -];};structC:a, B {};intMain () {C obj;      Obj.foo (); Obj.bar (); }
$ g++-Wall-o./test.&&./testA‘s this: 0x7fff57ddfb48B‘0x7fff57ddfb68

As you can see, the value of the this pointer is passed to B a method that is A larger than the method--the 32 actual size of a class A object. But what happens when we use the following function to invoke a method of a class using a pointer C ?

void call_by_ptr(constvoidconst) {    (obj.*mem_func)();}

In relation to what functions are called, different this pointer values are passed to these functions. But the call_by_ptr function does not know whether its arguments are foo() pointers or bar() pointers, and the only time that the information can be known is when these methods are used. This is why the pointer to the member function needs to know how to adjust the pointer before calling this . Now, we put all of them into a simple program that illustrates the mechanism of internal work:

#include <iostream>structAvoidFoo ()Const{STD::cout<<"A ' s this:\t"<< This<<STD:: Endl; }Charpad0[ +];};structBvoidBar ()Const{STD::cout<<"B ' s this:\t"<< This<<STD:: Endl; }Charpad2[ -];};structC:a, b{};voidCall_by_ptr (ConstC &obj,void(C::* mem_func) ()Const){void*data[2];STD::memcpy(Data, &mem_func,sizeof(Mem_func));STD::cout<<"------------------------------\ n"        "Object ptr:\t"<< &obj <<"\nfunction ptr:\t"<< data[0] <<"\npointer adj:\t"<< data[1] <<STD:: Endl; (Obj.*mem_func) ();}intMain () {C obj;    Call_by_ptr (obj, &c::foo); Call_by_ptr (obj, &c::bar);}
------------------------------Object ptr:    0x7fff535dfb28Function ptr:  0x10c620cacPointer adj:   0A‘s this:    0x7fff535dfb28------------------------------Object ptr:    0x7fff535dfb28Function ptr:  0x10c620cfePointer adj:   0x20B‘s this:    0x7fff535dfb48

Why is the function pointer in C + + 16 bytes

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.