Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C++, why do pointers to members of a class contains offsets rather than addresses?

Normally pointers contain addresses. Why do pointers to member of a class contain offsets?

Talking about pointers to class data members, not pointers to member functions.

like image 668
Nitesh Avatar asked Jul 26 '17 17:07

Nitesh


3 Answers

A pointer to a class member differs from a regular pointer in that it by itself doesn't actually point at a single location in memory. For example, if you have this setup:

struct MyStruct {
    int x;
    int y;
};

int MyStruct::* ptr = &MyStruct::y;

Then the pointer ptr isn't actually pointing to a memory address because there is no one object MyStruct::y. Rather, each instance of MyStruct has its own copy of the data member y.

The C++ standard doesn't mandate how pointers-to-member are actually implemented, but a common strategy is to have the pointer-to-member store an offset in bytes from the base of the object to the field in question. That way, when you write something like

MyStruct ms;
ms.*ptr = 137;

The compiler can generate code that says "go to the base address of ms, skip forward a number of bytes specified by the value stored in ptr, then write 137."

like image 110
templatetypedef Avatar answered Sep 21 '22 02:09

templatetypedef


Pointers do not have to contain addresses. Pointers are tools to access a certain object indirectly - i.e. write code which would access an object which is unknown at compile time. Example:

a = 10; // It is known at compile time, 10 is written to object a
*pi = 10; // It is not known at compile time where 10 is written to

For normal objects, having address in the pointer is a cheapest way to achieve this goal (however, it won't be the case for C++ script!).

For members, though, normal address wouldn't work - there is no such thing as an address of a member of the class! You can only know the physical address of the member when you have a class object.

So, you have to use some sort of offset, which you than can translate to physical address once the actual object is known.

like image 32
SergeyA Avatar answered Sep 18 '22 02:09

SergeyA


Pointers-to-members are not pointers.

The C++ type system contains several kinds of compound types, and there are two separate, sibling kinds of compound types that are not related to one another, despite having similar sounding names: Pointers, and "pointers to non-static class members". I'll call the latter "pointer-to-members", with hyphen, to stress that those are not a special kind of pointer, but really something entirely separate.

By the way, the type trait library separates the two concepts via std::is_pointer and std::is_member_pointer.

The two kinds of types serve entirely distinct purposes:

  • A pointer can represent the address of an object (or function) (or be null). That is, given a dereferenceable pointer, there is an actual concrete thing there that it's pointing at.

  • A pointer-to-member represents an abstract reference from a class to a non-static class member. Note that there are no objects involved. Such a pointer value does not point at anything concrete, and it has no concept of "dereferencing".

To repeat the final sentence: A pointer-to-member cannot be dereferenced, and it is not in any sense the address of an object. Rather, a pointer-to-member (specifically, to data member) can be applied to an object instance of its class, and together with the object it selects the subobject of that object corresponding to the class member that it represents. (Pointers-to-member-function have a slightly different notion of being applied to an instance; the result of the application is a function call.)

Returning to your question at last: A pointer holds an address of an object or function because it points at an object or function. A pointer-to-member does not hold an address, because it doesn't point at anything; it represents a relationship.

like image 26
Kerrek SB Avatar answered Sep 20 '22 02:09

Kerrek SB