C++ | Dereference a member pointer - c++

Well, lets say that I have a struct or a class that has a lets say int pointer as one of its members, something like this:
struct /*or class*/ some_struct /*or class*/ {
int *pointer = NULL;
} *obj_pointer;
and as the program goes obj_pointer and obj_pointer->pointer get initialized, how can I dereference obj_pointer->pointer so that I can print(cout) for example the value of the memory the pointer is pointing to?

Just like any other pointer, using the dereference operator *:
std::cout << *obj_pointer->pointer;
The member access operator -> have higher operator precedence than the dereference operator *

Related

overloading the operator ->

I was looking at overloading the -> operator. I came up with the following simple example:
struct foo
{
int p = 12;
};
struct A
{
foo* f;
A()
{
this->f = new foo();
}
foo* operator-> ()
{
return f;
}
};
int main()
{
A a;
std::cout << a->p; //output 12
}
Although this example works, yet I am hoping if someone could tell me why it works.
I was thinking that it should work like this
std::cout << a->->p; //The first arrow returns the pointer
//the second arrow dereferences it
but here it seems like a single arrow not only returns the pointer but it also dereferences it. Is this a special case in C++?
Yes, this is by-design, operator-> will be called recursively on the return value; then we can use such class (so-called smart pointers) in the same way as raw pointers.
If a user-defined operator-> is provided, the operator-> is called again on the value that it returns, recursively, until an operator-> is reached that returns a plain pointer. After that, built-in semantics are applied to that pointer.

Are there different uses of the arrow mark '->' used by pointers in C++? How exactly is it used?

Are there different uses of the -> symbol? (I think it's called overloading).
One of them that I know is that a pointer uses it to access a member of the object to which the pointer points to. For example:
class fruit{
char colour[10];
};
fruit mango;
fruit *pointertofruit = &mango; // Will it work without using the '&'?
pointertofruit->colour = '______';
Can I take it that the pointer is telling that "I point to an object whose data member is 'colour', so allow me to make that '______'"?
There are two uses for ->:
it dereferences a raw pointer to access a member (as you describe).
it is an operator that a class/struct can overload to return whatever it wants, as long as that something can also be dereferenced by ->. This is most commonly done in smart-pointer classes, like std::unique_ptr/std::shared_ptr, CComPtr/CComQIPtr, etc to dereference an internally held pointer, eg:
class fruit_ptr {
fruit *m_f;
public:
fruit_ptr(fruit *f) : m_f(f) {}
~fruit_ptr() { delete m_f; }
fruit* operator->(){ return m_f; }
};
fruit_ptr pointertofruit(new mango);
pointertofruit->colour = ...; // calls: pointertofruit.operator->()->colour = ...;

Dereferencing class with overloaded * operator

I'm trying to create a pointer to a class that have * operator overloaded, but it returns another value.
Class code:
template<class T> class Node
{
public:
T *pointer;
T& operator*()
{
return *pointer;
}
}
Then this code doesn't work, returning int instead of pointer:
Node<int>* examplePointer; //this works
Node<int> example; //creates an instance of Node<T> class
examplePointer = *example; //this doesn't work
How can I make pointers with overloaded * operator?
This Node<int>* example; means that example is a pointer on a Node<int> (yes, I am captain Obvious :) ).
If you use it afterward with *, that does mean that you're just dereferencing the pointer to accessto the Node<int>. So, basically you have something like:
*example; // Just a pointer dereference expression type
// is something like Node<int>
**example; // something like: example->operator*();
I do not really see what's your goal... Using a pointer to a container like this seems to creates a lot of indirection...
And more generally, you cannot overload an operator* outside a class definition, so you cannot define it for a pointer.
Try just Node<int> example. That gives you a Node, and *example will call your operator - so it behaves like a pointer.

C++ pointer and address clarification in relation to the current object

So far to my understanding, when defining a pointer variable, we are allocating space in RAM for that variable.
int *p;
Would define a space in RAM. Then we assign a memory address to that pointer using `&variable'.
I'm looking over at an example on: *this vs this in C++
The code is:
#include <iostream>
class Foo
{
public:
Foo()
{
this->value = 0;
}
Foo get_copy()
{
return *this;
}
Foo& get_copy_as_reference()
{
return *this;
}
Foo* get_pointer()
{
return this;
}
void increment()
{
this->value++;
}
void print_value()
{
std::cout << this->value << std::endl;
}
private:
int value;
};
int main()
{
Foo foo;
foo.increment();
foo.print_value();
foo.get_copy().increment();
foo.print_value();
foo.get_copy_as_reference().increment();
foo.print_value();
foo.get_pointer()->increment();
foo.print_value();
return 0;
}
I don't understand what the purpose of putting the * operator in front Foo* get_copy() and Foo* get_pointer() does. Why do I get an error if I removed the * from the Foo* functions while returning this not *this?
edit:
Also, why is:
foo.get_copy().increment();
foo.print_value();
yielding 1 not 2?
I don't understand what the purpose of putting the * operator in front Foo* get_copy() and Foo* get_pointer() does
Foo* get_pointer()
Foo* is a pointer that points to Foo object.
this is also a pointer that implicitly bind to the calling object of the member function. That's why the return type of those functions are Foo* not Foo.
The * is part of the type. So int means type int, and
int* type pointer to int. If the function returns pointer
to int, it is int* foo(), and if it retu rns a pointer to
Foo, it is Foo* Foo::get_pointer().
The definition reserves space for the defined object. A
declaration doesn't reserve any space, and definitions of things
that aren't objects (e.g. references or functions) don't reserve
any space either, at least not that you can see. (Obviously, a
function does exist somewhere in memory, and in many cases, the
compiler will need space as well for its implementation of a
reference. But they are invisible within the scope of C++.)
this, is always a pointer in C++, though you don't mention it explicitly anywhere. So while returning a this pointer, should use Foo*
this is actually an implicit object passed during function call, which is a pointer to the object which calls the function
It seems that you have changed the code from the example that you refer to so that get_copy() no longer returns a copy.
There are 2 ways of using * in your code example. One is for type declaration and the other is the dereferencing operator.
First the type declarations:
int *p means declaring p as a variable of type "pointer to an int".
Foo *get_pointer() means that the function get_pointer will return a value of type "pointer to a Foo object".
Now the dereferencing:
*p means "the value that p points to".
int a = 42;
int *p; // p is of type "pointer to an int"
p = &a; // set p to the address of a (p now "points to" a)
a = 117; // change the value of a
int x = *p; // set x to the value that p points to (which is a) - x will be 117
this is just a pointer to the object. *this means "the object that this points to". In your example this is of type Foo* (pointer to a Foo object) while *this is of type Foo (a Foo object).
"this" is a pointer.
you want to return a pointer to the instance (a specific allocated object).
Foo* get_pointer(){
return this;
}
or you want to return a pointer to the copy, allocate a new object.
//need to implement the copy here
Foo* get_copy(){
return this;
}
and not to the reference (address of the instance). this is why you need to return the pointer.

What are the pointer-to-member operators ->* and .* in C++?

Yes, I've seen this question and this FAQ, but I still don't understand what ->* and .* mean in C++.
Those pages provide information about the operators (such as overloading), but don't seem to explain well what they are.
What are ->* and .* in C++, and when do you need to use them as compared to -> and .?
I hope this example will clear things for you
//we have a class
struct X
{
void f() {}
void g() {}
};
typedef void (X::*pointer)();
//ok, let's take a pointer and assign f to it.
pointer somePointer = &X::f;
//now I want to call somePointer. But for that, I need an object
X x;
//now I call the member function on x like this
(x.*somePointer)(); //will call x.f()
//now, suppose x is not an object but a pointer to object
X* px = new X;
//I want to call the memfun pointer on px. I use ->*
(px ->* somePointer)(); //will call px->f();
Now, you can't use x.somePointer(), or px->somePointer() because there is no such member in class X. For that the special member function pointer call syntax is used... just try a few examples yourself ,you'll get used to it
EDIT: By the way, it gets weird for virtual member functions pointers.
For member variables:
struct Foo {
int a;
int b;
};
int main ()
{
Foo foo;
int (Foo :: * ptr);
ptr = & Foo :: a;
foo .*ptr = 123; // foo.a = 123;
ptr = & Foo :: b;
foo .*ptr = 234; // foo.b = 234;
}
Member functions are almost the same.
struct Foo {
int a ();
int b ();
};
int main ()
{
Foo foo;
int (Foo :: * ptr) ();
ptr = & Foo :: a;
(foo .*ptr) (); // foo.a ();
ptr = & Foo :: b;
(foo .*ptr) (); // foo.b ();
}
In a nutshell: You use -> and . if you know what member you want to access. And you use ->* and .* if you don't know what member you want to access.
Example with a simple intrusive list
template<typename ItemType>
struct List {
List(ItemType *head, ItemType * ItemType::*nextMemPointer)
:m_head(head), m_nextMemPointer(nextMemPointer) { }
void addHead(ItemType *item) {
(item ->* m_nextMemPointer) = m_head;
m_head = item;
}
private:
ItemType *m_head;
// this stores the member pointer denoting the
// "next" pointer of an item
ItemType * ItemType::*m_nextMemPointer;
};
When you have a normal pointer (to an object or a basic type), you would use * to dereference it:
int a;
int* b = a;
*b = 5; // we use *b to dereference b, to access the thing it points to
Conceptually, we're doing the same thing with a member function pointer:
class SomeClass
{
public: void func() {}
};
// typedefs make function pointers much easier.
// this is a pointer to a member function of SomeClass, which takes no parameters and returns void
typedef void (SomeClass::*memfunc)();
memfunc myPointer = &SomeClass::func;
SomeClass foo;
// to call func(), we could do:
foo.func();
// to call func() using our pointer, we need to dereference the pointer:
foo.*myPointer();
// this is conceptually just: foo . *myPointer ();
// likewise with a pointer to the object itself:
SomeClass* p = new SomeClass;
// normal call func()
p->func();
// calling func() by dereferencing our pointer:
p->*myPointer();
// this is conceptually just: p -> *myPointer ();
I hope that helps explain the concept. We're effectively dereferencing our pointer to the member function. It's a little more complicated than that -- it's not an absolute pointer to a function in memory, but just an offset, which is applied to foo or p above. But conceptually, we're dereferencing it, much like we would dereference a normal object pointer.
So called "pointers" to members in C++ are more like offsets, internally. You need both such a member "pointer", and an object, to reference the member in the object. But member "pointers" are used with pointer syntax, hence the name.
There are two ways you can have an object at hand: you have a reference to the object, or you have a pointer to the object.
For the reference, use .* to combine it with a member pointer, and for the pointer, use ->* to combine it with a member pointer.
However, as a rule, don't use member pointers if you can avoid it.
They obey pretty counter-intuitive rules, and they make it possible to circumvent protected access without any explicit casting, that is, inadvertently…
Cheers & hth.,
You cannot dereference pointer to members as normal pointers — because member functions require this pointer, and you have to pass it somehow. So, you need to use these two operators, with object on one side, and pointer on another, e.g. (object.*ptr)().
Consider using function and bind (std:: or boost::, depending on whether you write C++03 or 0x) instead of those, though.
Pointer-to-member access operators: .* and ->*
The pointer-to-member access operators, .* and ->*, are for dereferencing a pointer to member in combination with an object and a pointer to object, respectively. This description applies to both pointers to data members and pointers to member functions.
For example, consider the class Foo:
struct Foo {
int i;
void f();
};
If you declare a member pointer, iPtr, to an int data member of Foo:
int Foo::* iPtr;
You can initialize this member pointer iPtr so that it points to the Foo::i member:
iPtr = &Foo::i;
To dereference this pointer, you need to use it in conjunction with a Foo object.
Consider now the object foo and the pointer to object fooPtr:
Foo foo;
Foo* fooPtr = &foo;
Then, you can dereference iPtr in combination with foo or fooPtr:
foo.*iPtr = 0;
fooPtr->*iPtr = 0;
Analogously, you can use .* and ->* with pointers to function members. Note however that you will need to enclose them between parentheses because the function call operator, i.e., (), has higher precedence than both .* and ->*:
void (Foo::*memFuncPtr)() = &Foo::f;
(foo.*memFuncPtr)();
(fooPtr->*memFuncPtr)();
To conclude: you need an object to dereference a pointer to a member, and which one you use, either .* or ->* for dereferencing the pointer to member, depends on whether this needed object is directly provided or through an object pointer.
C++17 — Using std::invoke() instead
The use of both operators can be replaced since C++17 by the std::invoke function template. std::invoke provides a unified way of dereferencing member pointers regardless of whether you use them in combination with an object or an object pointer, and also regardless of whether the pointer to member corresponds to a pointer to data member or pointer to member function:
// dereference a pointer to a data member
std::invoke(iPtr, foo) = 0; // with an object
std::invoke(iPtr, fooPtr) = 0; // with an object pointer
// dereference a pointer to a member function
std::invoke(memFuncPtr, foo); // with an object
std::invoke(memFuncPtr, fooPtr); // with an object pointer
This unified syntax corresponds to the ordinary function call syntax, and it may make it easier to write generic code.