314

I came across this strange code snippet which compiles fine:

class Car
{
    public:
    int speed;
};

int main()
{
    int Car::*pSpeed = &Car::speed;
    return 0;
}

Why does C++ have this pointer to a non-static data member of a class? What is the use of this strange pointer in real code?

L. F.
  • 19,445
  • 8
  • 48
  • 82
Ashwin Nanjappa
  • 76,204
  • 83
  • 211
  • 292
  • Here's where I found it, confused me too...but makes sense now: http://stackoverflow.com/a/982941/211160 – HostileFork says dont trust SE Jul 12 '12 at 06:03
  • 3
    Pointer to members are C++'s typesafe alternative to the rather unsafe `offsetof()` construct from C. They both return the information, where inside a `class` or `struct` a certain field is located. – Kai Petzke Feb 18 '21 at 06:44

19 Answers19

247

It's a "pointer to member" - the following code illustrates its use:

#include <iostream>
using namespace std;

class Car
{
    public:
    int speed;
};

int main()
{
    int Car::*pSpeed = &Car::speed;

    Car c1;
    c1.speed = 1;       // direct access
    cout << "speed is " << c1.speed << endl;
    c1.*pSpeed = 2;     // access via pointer to member
    cout << "speed is " << c1.speed << endl;
    return 0;
}

As to why you would want to do that, well it gives you another level of indirection that can solve some tricky problems. But to be honest, I've never had to use them in my own code.

Edit: I can't think off-hand of a convincing use for pointers to member data. Pointer to member functions can be used in pluggable architectures, but once again producing an example in a small space defeats me. The following is my best (untested) try - an Apply function that would do some pre &post processing before applying a user-selected member function to an object:

void Apply( SomeClass * c, void (SomeClass::*func)() ) {
    // do hefty pre-call processing
    (c->*func)();  // call user specified function
    // do hefty post-call processing
}

The parentheses around c->*func are necessary because the ->* operator has lower precedence than the function call operator.

Oktalist
  • 14,336
  • 3
  • 43
  • 63
  • 4
    Could you show an example of a tricky situation where this is useful? Thanks. – Ashwin Nanjappa Mar 22 '09 at 09:31
  • I have an example of using pointer-to-member in a Traits class in [another SO answer](http://stackoverflow.com/questions/5650199/using-template-instead-of-switch/5650423#5650423). – Mike DeSimone Apr 13 '11 at 19:08
  • An example is writing a "callback"-type class for some event-based system. CEGUI’s UI event subscription system, for example, takes a templated callback that stores a pointer to a member function of your choosing, so that you can specify a method to handle the event. – Benji XVI Dec 28 '12 at 21:03
  • 3
    There is a pretty cool example of pointer-to-**data**-member usage in a template function [in this code](http://www.keithschwarz.com/interesting/code/?dir=inplace-tree-delete) – alveko Jun 06 '13 at 22:43
  • 5
    I have recently used pointers to data members in serialization framework. Static marshaller object was initialized with list of wrappers containing pointer to serializable data members. [An early prototype of this code.](http://ideone.com/MIHQAM) – Alexey Biryukov Apr 08 '15 at 22:25
  • I once encountered a very good usage of pointer to member function. Consider a class with a single function which is going to be called many times. except the behavior of that function is based on the class state. In my case it was a canvas class, and the function was basically putpixel. The state was bit-rate of contained image. Obviously the bitrate is not going to change very often. First I implemented the putpixel using switch/case structure. Later I defined different member functions for each bitrate, and set a p2f to call which was set at state change. The result was 50% faster. – Ali1S232 Jul 25 '16 at 00:35
  • @Ali.S A faster way might be to pass a callback function object for putpixel, instead of passing a `void(Canvas::*func)()`, wouldn't it? It would be comparable to passing a function pointer vs passing a function object into `std::sort()` - the latter will be inlined and hence be significantly faster. – Bernard Jun 28 '17 at 03:52
  • I had a [simple case](https://stackoverflow.com/questions/67384979/point-to-a-struct-member) where pointer member was super usefull – Ivan May 04 '21 at 15:47
125

This is the simplest example I can think of that conveys the rare cases where this feature is pertinent:

#include <iostream>

class bowl {
public:
    int apples;
    int oranges;
};

int count_fruit(bowl * begin, bowl * end, int bowl::*fruit)
{
    int count = 0;
    for (bowl * iterator = begin; iterator != end; ++ iterator)
        count += iterator->*fruit;
    return count;
}

int main()
{
    bowl bowls[2] = {
        { 1, 2 },
        { 3, 5 }
    };
    std::cout << "I have " << count_fruit(bowls, bowls + 2, & bowl::apples) << " apples\n";
    std::cout << "I have " << count_fruit(bowls, bowls + 2, & bowl::oranges) << " oranges\n";
    return 0;
}

The thing to note here is the pointer passed in to count_fruit. This saves you having to write separate count_apples and count_oranges functions.

John McFarlane
  • 5,528
  • 4
  • 34
  • 38
  • 3
    Shouldn't it be `&bowls.apples` and `&bowls.oranges`? `&bowl::apples` and `&bowl::oranges` doesn't point to anything. – Dan Nissenbaum Mar 30 '14 at 09:20
  • 27
    `&bowl::apples` and `&bowl::oranges` do not point to members of an _object_; they point to members of a _class_. They need to be combined with a pointer to an actual object before they point to something. That combination is achieved with the `->*` operator. – John McFarlane Mar 30 '14 at 20:56
  • Thank you very much for this very illustrative example! Nevertheless, I think I still don't fully understand the expression: `int bowl::*fruit`. What is the type and what is the parameter name of this expression? – fabian Apr 12 '21 at 17:37
  • 1
    @fabian YW! The parameter name is `fruit`. It's type says, "I point to an `int` that's a member of the `bowl` class." Under the hood, it's typically implemented as an offset from the start of the class, i.e. 0 bytes for `apples` or 4 bytes for `oranges`. Here's [a simpler example with a function that just increments a member](https://godbolt.org/z/h8sKb45he). `fruit` specifies where in `b` that member variable is as a byte offset. And here's [the calling code](https://godbolt.org/z/364G8T9G5) which either passes `0` or `4` in as that offset. – John McFarlane Apr 12 '21 at 20:53
  • 1
    Excellent answer. The only thing it's missing is pointing out that using an alias can make pointers to members nicer to work with. If you added `using fruit_member_ptr = int bowl::*;` then the last argument to `count_fruit` could be just `fruit_member_ptr fruit`, which should read a lot more naturally to most people. I recommend doing this whenever working with pointers to functions, methods or data members. – Parker Coates Jan 12 '23 at 13:23
70

Another application are intrusive lists. The element type can tell the list what its next/prev pointers are. So the list does not use hard-coded names but can still use existing pointers:

// say this is some existing structure. And we want to use
// a list. We can tell it that the next pointer
// is apple::next.
struct apple {
    int data;
    apple * next;
};

// simple example of a minimal intrusive list. Could specify the
// member pointer as template argument too, if we wanted:
// template<typename E, E *E::*next_ptr>
template<typename E>
struct List {
    List(E *E::*next_ptr):head(0), next_ptr(next_ptr) { }

    void add(E &e) {
        // access its next pointer by the member pointer
        e.*next_ptr = head;
        head = &e;
    }

    E * head;
    E *E::*next_ptr;
};

int main() {
    List<apple> lst(&apple::next);

    apple a;
    lst.add(a);
}
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
50

Here's a real-world example I am working on right now, from signal processing / control systems:

Suppose you have some structure that represents the data you are collecting:

struct Sample {
    time_t time;
    double value1;
    double value2;
    double value3;
};

Now suppose that you stuff them into a vector:

std::vector<Sample> samples;
... fill the vector ...

Now suppose that you want to calculate some function (say the mean) of one of the variables over a range of samples, and you want to factor this mean calculation into a function. The pointer-to-member makes it easy:

double Mean(std::vector<Sample>::const_iterator begin, 
    std::vector<Sample>::const_iterator end,
    double Sample::* var)
{
    float mean = 0;
    int samples = 0;
    for(; begin != end; begin++) {
        const Sample& s = *begin;
        mean += s.*var;
        samples++;
    }
    mean /= samples;
    return mean;
}

...
double mean = Mean(samples.begin(), samples.end(), &Sample::value2);

Note Edited 2016/08/05 for a more concise template-function approach

And, of course, you can template it to compute a mean for any forward-iterator and any value type that supports addition with itself and division by size_t:

template<typename Titer, typename S>
S mean(Titer begin, const Titer& end, S std::iterator_traits<Titer>::value_type::* var) {
    using T = typename std::iterator_traits<Titer>::value_type;
    S sum = 0;
    size_t samples = 0;
    for( ; begin != end ; ++begin ) {
        const T& s = *begin;
        sum += s.*var;
        samples++;
    }
    return sum / samples;
}

struct Sample {
    double x;
}

std::vector<Sample> samples { {1.0}, {2.0}, {3.0} };
double m = mean(samples.begin(), samples.end(), &Sample::x);

EDIT - The above code has performance implications

You should note, as I soon discovered, that the code above has some serious performance implications. The summary is that if you're calculating a summary statistic on a time series, or calculating an FFT etc, then you should store the values for each variable contiguously in memory. Otherwise, iterating over the series will cause a cache miss for every value retrieved.

Consider the performance of this code:

struct Sample {
  float w, x, y, z;
};

std::vector<Sample> series = ...;

float sum = 0;
int samples = 0;
for(auto it = series.begin(); it != series.end(); it++) {
  sum += *it.x;
  samples++;
}
float mean = sum / samples;

On many architectures, one instance of Sample will fill a cache line. So on each iteration of the loop, one sample will be pulled from memory into the cache. 4 bytes from the cache line will be used and the rest thrown away, and the next iteration will result in another cache miss, memory access and so on.

Much better to do this:

struct Samples {
  std::vector<float> w, x, y, z;
};

Samples series = ...;

float sum = 0;
float samples = 0;
for(auto it = series.x.begin(); it != series.x.end(); it++) {
  sum += *it;
  samples++;
}
float mean = sum / samples;

Now when the first x value is loaded from memory, the next three will also be loaded into the cache (supposing suitable alignment), meaning you don't need any values loaded for the next three iterations.

The above algorithm can be improved somewhat further through the use of SIMD instructions on eg SSE2 architectures. However, these work much better if the values are all contiguous in memory and you can use a single instruction to load four samples together (more in later SSE versions).

YMMV - design your data structures to suit your algorithm.

Tom
  • 7,269
  • 1
  • 42
  • 69
42

You can later access this member, on any instance:

int main()
{    
  int Car::*pSpeed = &Car::speed;    
  Car myCar;
  Car yourCar;

  int mySpeed = myCar.*pSpeed;
  int yourSpeed = yourCar.*pSpeed;

  assert(mySpeed > yourSpeed); // ;-)

  return 0;
}

Note that you do need an instance to call it on, so it does not work like a delegate.
It is used rarely, I've needed it maybe once or twice in all my years.

Normally using an interface (i.e. a pure base class in C++) is the better design choice.

peterchen
  • 40,917
  • 20
  • 104
  • 186
  • But surely this is just bad practice? should do something like youcar.setspeed(mycar.getpspeed) – thecoshman Oct 06 '10 at 21:08
  • 13
    @thecoshman: entirely depends - hiding data members behind set/get methods is not encapsulation and merely a milkmaids attempt at interface abstraction. In many scenarios, "denormalization" to public members is a reasonable choice. But that discussion probably exceeds the confines of the comment functionality. – peterchen Oct 12 '10 at 15:21
  • 5
    +1 for pointing out, if I understand correctly, that this is a pointer to a member of any instance, and not a pointer to a specific value of one instance, which is the part I was completely missing. – johnbakers May 21 '13 at 09:49
  • @Fellowshee You do understand correctly :) (emphasized that in the answer). – peterchen May 22 '13 at 16:58
27

IBM has some more documentation on how to use this. Briefly, you're using the pointer as an offset into the class. You can't use these pointers apart from the class they refer to, so:

  int Car::*pSpeed = &Car::speed;
  Car mycar;
  mycar.*pSpeed = 65;

It seems a little obscure, but one possible application is if you're trying to write code for deserializing generic data into many different object types, and your code needs to handle object types that it knows absolutely nothing about (for example, your code is in a library, and the objects into which you deserialize were created by a user of your library). The member pointers give you a generic, semi-legible way of referring to the individual data member offsets, without having to resort to typeless void * tricks the way you might for C structs.

AHelps
  • 1,782
  • 11
  • 17
  • Could you share a code snippet example where this construct is useful? Thanks. – Ashwin Nanjappa Mar 22 '09 at 09:32
  • 2
    I'm currently doing alot of this due to doing some DCOM work and using managed resource classes which involves doing a bit of work before each call, and using data members for internal representation to send off to com, plus templating,makes a lot of boiler plate code *much* smaller – Dan Aug 10 '09 at 21:30
21

It makes it possible to bind member variables and functions in the uniform manner. The following is example with your Car class. More common usage would be binding std::pair::first and ::second when using in STL algorithms and Boost on a map.

#include <list>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>


class Car {
public:
    Car(int s): speed(s) {}
    void drive() {
        std::cout << "Driving at " << speed << " km/h" << std::endl;
    }
    int speed;
};

int main() {

    using namespace std;
    using namespace boost::lambda;

    list<Car> l;
    l.push_back(Car(10));
    l.push_back(Car(140));
    l.push_back(Car(130));
    l.push_back(Car(60));

    // Speeding cars
    list<Car> s;

    // Binding a value to a member variable.
    // Find all cars with speed over 60 km/h.
    remove_copy_if(l.begin(), l.end(),
                   back_inserter(s),
                   bind(&Car::speed, _1) <= 60);

    // Binding a value to a member function.
    // Call a function on each car.
    for_each(s.begin(), s.end(), bind(&Car::drive, _1));

    return 0;
}
Alex B
  • 82,554
  • 44
  • 203
  • 280
11

You can use an array of pointer to (homogeneous) member data to enable a dual, named-member (i.e. x.data) and array-subscript (i.e. x[idx]) interface.

#include <cassert>
#include <cstddef>

struct vector3 {
    float x;
    float y;
    float z;

    float& operator[](std::size_t idx) {
        static float vector3::*component[3] = {
            &vector3::x, &vector3::y, &vector3::z
        };
        return this->*component[idx];
    }
};

int main()
{
    vector3 v = { 0.0f, 1.0f, 2.0f };

    assert(&v[0] == &v.x);
    assert(&v[1] == &v.y);
    assert(&v[2] == &v.z);

    for (std::size_t i = 0; i < 3; ++i) {
        v[i] += 1.0f;
    }

    assert(v.x == 1.0f);
    assert(v.y == 2.0f);
    assert(v.z == 3.0f);

    return 0;
}
Functastic
  • 606
  • 3
  • 12
  • I've more often seen this implemented using an anonymous union including an array field v[3] since that avoids an indirection, but clever nonetheless, and potentially useful for non-contiguous fields. – Dwayne Robinson Apr 21 '15 at 04:28
  • 3
    @DwayneRobinson but using a `union` to type-pun in that fashion is not allowed by the standard as it invokes numerous forms of undefined behaviour... whereas this answer is ok. – underscore_d Sep 07 '16 at 22:25
  • That's a neat example but operator[] can be rewritten without pointer-to-component: `float *component[] = { &x, &y, &z }; return *component[idx];` I.e., the pointer-to-component seems to serve no purpose except obfuscation. – tobi_s May 21 '20 at 03:20
2

Pointers to classes are not real pointers; a class is a logical construct and has no physical existence in memory, however, when you construct a pointer to a member of a class it gives an offset into an object of the member's class where the member can be found; This gives an important conclusion: Since static members are not associated with any object so a pointer to a member CANNOT point to a static member(data or functions) whatsoever Consider the following:

class x {
public:
    int val;
    x(int i) { val = i;}

    int get_val() { return val; }
    int d_val(int i) {return i+i; }
};

int main() {
    int (x::* data) = &x::val;               //pointer to data member
    int (x::* func)(int) = &x::d_val;        //pointer to function member

    x ob1(1), ob2(2);

    cout <<ob1.*data;
    cout <<ob2.*data;

    cout <<(ob1.*func)(ob1.*data);
    cout <<(ob2.*func)(ob2.*data);


    return 0;
}

Source: The Complete Reference C++ - Herbert Schildt 4th Edition

shycha
  • 440
  • 5
  • 13
Arijit Dey
  • 21
  • 3
2

One way I've used it is if I have two implementations of how to do something in a class and I want to choose one at run-time without having to continually go through an if statement i.e.

class Algorithm
{
public:
    Algorithm() : m_impFn( &Algorithm::implementationA ) {}
    void frequentlyCalled()
    {
        // Avoid if ( using A ) else if ( using B ) type of thing
        (this->*m_impFn)();
    }
private:
    void implementationA() { /*...*/ }
    void implementationB() { /*...*/ }

    typedef void ( Algorithm::*IMP_FN ) ();
    IMP_FN m_impFn;
};

Obviously this is only practically useful if you feel the code is being hammered enough that the if statement is slowing things done eg. deep in the guts of some intensive algorithm somewhere. I still think it's more elegant than the if statement even in situations where it has no practical use but that's just my opnion.

Troubadour
  • 13,334
  • 2
  • 38
  • 57
  • Basically, you can achieve the same with the abstract `Algorithm` and two derived classes, e.g., `AlgorithmA` and `AlgorithmB`. In such a case both algorithms are well separated and are ensured to be tested independently. – shycha Apr 10 '19 at 13:31
0

Here is an example where pointer to data members could be useful:

#include <iostream>
#include <list>
#include <string>

template <typename Container, typename T, typename DataPtr>
typename Container::value_type searchByDataMember (const Container& container, const T& t, DataPtr ptr) {
    for (const typename Container::value_type& x : container) {
        if (x->*ptr == t)
            return x;
    }
    return typename Container::value_type{};
}

struct Object {
    int ID, value;
    std::string name;
    Object (int i, int v, const std::string& n) : ID(i), value(v), name(n) {}
};

std::list<Object*> objects { new Object(5,6,"Sam"), new Object(11,7,"Mark"), new Object(9,12,"Rob"),
    new Object(2,11,"Tom"), new Object(15,16,"John") };

int main() {
    const Object* object = searchByDataMember (objects, 11, &Object::value);
    std::cout << object->name << '\n';  // Tom
}
prestokeys
  • 4,817
  • 3
  • 20
  • 43
0

Suppose you have a structure. Inside of that structure are * some sort of name * two variables of the same type but with different meaning

struct foo {
    std::string a;
    std::string b;
};

Okay, now let's say you have a bunch of foos in a container:

// key: some sort of name, value: a foo instance
std::map<std::string, foo> container;

Okay, now suppose you load the data from separate sources, but the data is presented in the same fashion (eg, you need the same parsing method).

You could do something like this:

void readDataFromText(std::istream & input, std::map<std::string, foo> & container, std::string foo::*storage) {
    std::string line, name, value;

    // while lines are successfully retrieved
    while (std::getline(input, line)) {
        std::stringstream linestr(line);
        if ( line.empty() ) {
            continue;
        }

        // retrieve name and value
        linestr >> name >> value;

        // store value into correct storage, whichever one is correct
        container[name].*storage = value;
    }
}

std::map<std::string, foo> readValues() {
    std::map<std::string, foo> foos;

    std::ifstream a("input-a");
    readDataFromText(a, foos, &foo::a);
    std::ifstream b("input-b");
    readDataFromText(b, foos, &foo::b);
    return foos;
}

At this point, calling readValues() will return a container with a unison of "input-a" and "input-b"; all keys will be present, and foos with have either a or b or both.

inetknght
  • 4,300
  • 1
  • 26
  • 52
0

Just to add some use cases for @anon's & @Oktalist's answer, here's a great reading material about pointer-to-member-function and pointer-to-member-data.

https://www.dre.vanderbilt.edu/~schmidt/PDF/C++-ptmf4.pdf

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
Dragonly
  • 55
  • 7
  • 1
    the link has been dead. That's why link-only answers are not expected here. At least summarize the content of the link, otherwise your answer becomes invalid when the link rots – phuclv Sep 03 '19 at 05:35
0

Pointer to members are C++'s type safe equivalent for C's offsetof(), which is defined in stddef.h: Both return the information, where a certain field is located within a class or struct. While offsetof() may be used with certain simple enough classes also in C++, it fails miserably for the general case, especially with virtual base classes. So pointer to members were added to the standard. They also provide easier syntax to reference an actual field:

struct C { int a; int b; } c;
int C::* intptr = &C::a;       // or &C::b, depending on the field wanted
c.*intptr += 1;

is much easier than:

struct C { int a; int b; } c;
int intoffset = offsetof(struct C, a);
* (int *) (((char *) (void *) &c) + intoffset) += 1;

As to why one wants to use offsetof() (or pointer to members), there are good answers elsewhere on stackoverflow. One example is here: How does the C offsetof macro work?

Kai Petzke
  • 2,150
  • 21
  • 29
0

with pointer to member, we can write generic code like this

template<typename T, typename U>
struct alpha{
   T U::*p_some_member;
};

struct beta{
   int foo;
};

int main()
{

   beta b{};

   alpha<int, beta> a{&beta::foo};

   b.*(a.p_some_member) = 4;

   return 0;
}
0

I love the * and & operators:

struct X 
{ 
    int a {0}; 
    int *ptr {NULL};

    int &fa() { return a; }
    int *&fptr() { return ptr; }
};

int main(void) 
{
    X x;
    int X::*p1 = &X::a;     // pointer-to-member 'int X::a'. Type of p1 = 'int X::*'
    x.*p1 = 10;

    int *X::*p2 = &X::ptr;  // pointer-to-member-pointer 'int *X::ptr'. Type of p2 = 'int *X::*' 
    x.*p2 = nullptr;
    X *xx;
    xx->*p2 = nullptr;

    int& (X::*p3)() = X::fa; // pointer-to-member-function 'X::fa'. Type of p3 = 'int &(X::*)()'
    (x.*p3)() = 20; 
    (xx->*p3)() = 30;

    int *&(X::*p4)() = X::fptr;  // pointer-to-member-function 'X::fptr'. Type of p4 = 'int *&(X::*)()'
    (x.*p4)() = nullptr; 
    (xx->*p4)() = nullptr;
}

Indeed all is true as long as the members are public, or static

mada
  • 1,646
  • 1
  • 15
0

Here is an example using this syntax to write a template algorithm for copying a single member of a struct out of an array of that struct, placing it in an array of the type of the member:

/// @param member A pointer to the struct/class member like `&MyClass::name_of_member`.
/// Note this is a pointer to the member in the class, not a pointer to an instance of it
/// in an instance of the the class.
template <typename InputIterator, typename OutputIterator, typename MemberType, typename StructType>
void extract_member(const InputIterator input, const InputIterator end, OutputIterator output, MemberType StructType::*member) {
    std::transform(input, end, output, [member](const StructType& obj) {
        return obj.*member;
    });
}

Here is how you would use it:

extract_member(std::begin(struct_container), std::end(struct_container), std::begin(scalar_container), &MyClass::name_of_member);
// (scalar_container is presized or you could use a back inserter)

This syntax allows you to specify to the generic helper function which member to select.

ahcox
  • 9,349
  • 5
  • 33
  • 38
-1

A realworld example of a pointer-to-member could be a more narrow aliasing constructor for std::shared_ptr:

template <typename T>
template <typename U>
shared_ptr<T>::shared_ptr(const shared_ptr<U>, T U::*member);

What that constructor would be good for

assume you have a struct foo:

struct foo {
    int ival;
    float fval;
};

If you have given a shared_ptr to a foo, you could then retrieve shared_ptr's to its members ival or fval using that constructor:

auto foo_shared = std::make_shared<foo>();
auto ival_shared = std::shared_ptr<int>(foo_shared, &foo::ival);

This would be useful if want to pass the pointer foo_shared->ival to some function which expects a shared_ptr

https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr

benb
  • 174
  • 2
  • 4
  • Yes, but `auto ival_shared = std::shared_ptr(foo_shared, &foo_shared->ival);` would do the same job, using the existing standard library, and without ever using pointers-to-members. So this answer leaves OP still asking "but _why_ would I want to do that?" – Quuxplusone Jan 13 '21 at 20:39
-1

I think you'd only want to do this if the member data was pretty large (e.g., an object of another pretty hefty class), and you have some external routine which only works on references to objects of that class. You don't want to copy the member object, so this lets you pass it around.

Andrew Jaffe
  • 26,554
  • 4
  • 50
  • 59