Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

About sizeof of a class member function pointer [duplicate]

Let's say we have a class A

class A;

and these typedefs

typedef void (A::*a_func_ptr)(void);
typedef void (*func_ptr)(void);

My question is why sizeof(a_func_ptr) returns 16, while sizeof(func_ptr) returns 4 (as for any pointer on x86 system)?

For instance

int main(int argc, char *argv[])
{
  int a = sizeof(a_func_ptr);
  int b = sizeof(func_ptr);
}
like image 681
Alex G Avatar asked Apr 17 '13 14:04

Alex G


People also ask

What is the size of function pointer?

A function-pointer is a 4-byte elementary item . Function-pointers have the same capabilities as procedure-pointers, but are 4 bytes in length instead of 8 bytes. Function-pointers are thus more easily interoperable with C function pointers.

What is pointer member function?

Pointers to members allow you to refer to nonstatic members of class objects. You cannot use a pointer to member to point to a static class member because the address of a static member is not associated with any particular object.

What is std:: function in c++?

Class template std::function is a general-purpose polymorphic function wrapper. Instances of std::function can store, copy, and invoke any Callable target -- functions, lambda expressions, bind expressions, or other function objects, as well as pointers to member functions and pointers to data members.


2 Answers

My question is why sizeof(a_func_ptr) returns 16, while sizeof(func_ptr) returns 4 (as for any pointer on x86 system)?

Because pointer-to-members are implemented differently. They're not pointers under the hood. Some compilers, such as MSVC, implement them as struct with more than one members in it.

Read this interesting article:

  • Pointers to member functions are very strange animals

Note that in some compilers, they might have same size. The bottomline is: they're compiler-dependent.

like image 162
Nawaz Avatar answered Sep 23 '22 00:09

Nawaz


Consider the following:

#include <iostream>

class A {
public:
    virtual void foo(){ std::cout << "A::foo" << std::endl; }
    void bar(){ std::cout << "A::bar" << std::endl; }
};

class B : public A {
public:
     void foo(){  std::cout << "B::foo" << std::endl; }
     void bar(){ std::cout << "B::bar" << std::endl; }
};

typedef void (A::*a_func_ptr)(void);

int main() {
   a_func_ptr f = &A::foo;
   a_func_ptr g = &A::bar;
   B b;
   A a;
   (b.*f)();
   (b.*g)();
   (a.*f)();
   (a.*g)();
}

Output:

B::foo
A::bar
A::foo
A::bar

Both member pointers are of the same type, yet both correctly routed the call in every cases.

Somehow, the generated programme must know when a pointer to method is actually a simple method or a virtual one. Thus the runtime representation of a method pointer has to include more information to handle the second case.

Remark: the size seems to be implementation dependent (I get 8 on my system).

like image 37
didierc Avatar answered Sep 25 '22 00:09

didierc