Why won't [ ] brackets work when dereferencing a pointer? - c++

If I have a std::vector, I can access a member because the square bracket operator is overloaded in the vector class. If I have a pointer to a vector, I can dereference the pointer and use this operator. But with the arrow -> operator it won't let me use it. Example:
// Excuse the UB here, it's just for illustration
std::vector<int> myVector;
std::vector<int>* pToVector;
myVector[4] = 0; // Works fine
(*pToVector)[4] = 0; // Works fine
pToVector->[4] = 0; // Doesn't work
(pToVector->)[4] = 0; // Doesn't work
Seeing as though the -> arrow operator dereferences the pointer, is there a reason not to expect that this would work? Or is it just one of those things about the language?
Thanks.

std::vector<int> myVector;
std::vector<int>* pToVector;
myVector[4] = 0; // Works fine.
(*pToVector)[4] = 0; // Works fine
pToVector->[4] = 0; // Doesn't work
(pToVector->)[4] = 0; // Doesn't work
If you must use a pointer to an object to access an overloaded operator of the object's class, you will have to call it explicitly.
pToVector->operator[](4)
... By the way, Accessing an index outside myVector.size() is Undefined Behavior. This includes the statements with the comment annotation in your code about // Works fine.

The correct syntax for the second two lines would be:
(*pToVector)[4] = 0;
//dereference the pointer and then call operator[] on the object returned by the dereference
You could use the -> operator to access regular member functions like this:
pToVector->size();
Technically you could try yo call the operator[] by name but it is more verbose.

The reason is that [] is an operator, and the short operator syntax does not require or allow member access operators. This applies to both member access operators . and ->, which makes sense because the latter is just shorthand for (*a).b.
E.g. all disallowed a. & b, a->^b
Technically, it also applies to the rarer .* and ->*. Note that the latter is not -> followed by operator*, but a pointer to member pointer dereference.

-> operator is replacement for dot operator, except it dereferences a pointer first. It is used to access attributes(members and functions). For your operation, operator[] is the attribute. So, pToVector->operator[](4) is applied to (*pToVector)[4] = 0

The -> operator does not just dereference, it also accesses a member. You are accessing an element*, not a member. -> could have been defined to allow that, but wasn't.
* To be more precise, a vector is letting you access an object as if it were an element of an array, but it doesn't change the syntax.

I think the square brackets dereference the pointer, so you ended up dereferencing twice there.
ptoVector[4] I think would have worked and been sufficient since the square brackets do a dereference for you.

Related

C++ Why the operator-> breaks the nested operator() call?

When I use the dereference operator on the pointer to class with overloaded opearator() (aka functors) - it works like a charm:
struct Functor {
int operator()(int a, float b) {
return a+b;
}
};
Functor g;
Functor * f = &g;
g(1,2.);
(*f)(1,.2);
f->operator()(1,2.f);
But the form
// f->(1,2.f); // doesn't compile (expected unqualified-id)
Why is that?
In C++, the dot (.) operator is used to access members and call methods on an object. In your example, you could have used in the following way:
g.operator()(1, 2.);
and it would have compiled fine. Instead, you call the operator in the equivalent (and more conventional) notation, as follows:
g(1,2.);
which is nice and clean. What you are trying to do is achieve the same clean operator call, but from a pointer, using the -> notation, thinking that the same magic will apply. Sadly, it does not work that way. In C++, p->a() is a shorthand for (*p).a(). It is, in other words, a way to
dereference a pointer -- *p;
call a method (or access a member) from that dereferenced object -- (*p).a();
That dereferenced object is no longer a pointer (the parenthesis around *p achieve that), which is why the dot operator can be called. So when you write:
f->(1,2.f);
what you are writing is something like:
(*f).(1, 2.f);
which is not valid C++ since (*f) does not represent an address to a Functor object. Note that:
f->operator()(1,2.f);
is valid because it means:
(*f).operator()(1, 2.f);
which works. It is equivalent to the first line I wrote above: g.operator()(1, 2.);.
Hope this helps.

dereferencing pointers using "this"

I am trying to call a variable in my class using the this keyword in two ways but I am confused with the 2nd way. The correct way of dereferencing happens to be "(*this).num" however, I was wondering why "*(this).num" is not right as well. The error I get with *(this).num is
request for member 'num' in 'this', which is of pointer type çlass const'*
class::class(int n): num(n)
{
cout << "num= " << num << endl;
cout << "this->num" << this->num << endl;
cout << "(*this).num" << (*this).num << endl;
}
Because if you define
int i = 9;
int *ptr = &i;
cout<<*(ptr)<<endl;
and call *(ptr) it works. But why doesn't it work in my class?
It's simply a matter of operator precedence. The binary dot operator has a higher precedence than the unary star operator, so *(this).num (the parentheses have no effect there) is interpreted as *(this.num), and not as (*this).num. The compiler is telling you that, because this is a pointer, this.num doesn't make sense: you can't apply the dot operator directly to a pointer.
You are using two operators: the indirection/dereferincing operator * and the member access operator ..
If you have a look at the precedence of these operators, you'll see that . has higher precedence than * (that is, . will be applied before *), so thus *(this).num is basically the same as writing *(this.num).
Since this is a pointer, you can't use the . operator on it, which is also what the error message is telling you (try using -> instead).
The reason why your second example works, is that you're not using the . operator, and thus there is no precedence to be messed up.
. has higher precedence than *.
So writing *(this).num is equivalent to (*((this).num))). Or *(this.num).
Your second example is completely different from the first since there is no access to members . or ->.
If you don't know all the precedences, or even if you do, it's usually more readable to add the appropriate brackets.
One works and the other doesn't because they are not the same thing!
*(ptr) and *(this) are the same, but *(this).num and (*this).num are not the same, that's the whole point of adding the parentheses! They change how the sub-expressions are grouped, just like in mathematics.
The parentheses in (ptr) and (this) are completely redundant, you are grouping a single sub-expression, which does nothing. In (*this) it's not redundant, it ensures that you dereference the pointer, so in (*this).num it dereferences the pointer first and then the member access .num is applied to the result of that dereference.
Compare it to mathematics:
(1) is just 1, and similarly (ptr) is just ptr
-(1) is just -1, and similarly *(ptr) is just *ptr
But -(1 + 3) and -(1) + 3 are completely different, because you change the order of the operators.
Similarly, *(this.num) and (*this).num are completely different.
The short answer is syntax.
(ptr) looks like this: evaluate expr inside () first, then dereference the result which is in this case is int. It's fine, the same as *ptr.
*(this).num is eq. with *this.num which means get the num member of this. After that dereference num. It's incorrect as you can see because "this" is a pointer to the current object.
(*this).num means dereference this, then get the num member.

Elements of dynamically allocated array don't use -> operator after first element?

I'm reading a tutorial on C++ that demonstrates how to call an object's public methods from an element of an array using the subscript syntax. It goes something like this:
Foo* array = new Foo[2];
array->public_function();
array[1].public_function();
Now I understand that the variable array points to the first element of the array and thus uses the -> operator to access that element's public data and functions. My question is, why would the call to the array[1] be any different - why would it use the . syntax as opposed to the -> syntax? Aren't all elements of the array pointers?
Once you use the indexing [], you get the object, not the pointer to the object.
Consider the following example, which works with the pointer directly by using pointer arithmetic.
Foo* array = new Foo[2];
// Following four are equivalent.
array[0].public_function();
array->public_function();
(array + 0)->public_function();
(&array[0])->public_function();
// Following three are equivalent.
array[1].public_function();
(array + 1)->public_function();
(&array[1])->public_function();
You can think of it as if the [] operator returns a reference to Foo, so you use the . operator to access its members.
array->public_function() is the same as (*array).public_function() which is the same as array[0].public_function(). You are accessing public_function() through a raw pointer to a Foo object instance. The compiler has no concept that the pointer is actually an array of Foo instances. Like you said, array is just a pointer to the first element in the array. All of the above syntaxes are valid on any object pointer. Since you are dealing with an array, you should stick with the array[0].public_function() syntax for consistency and readibility.

c++ question, about * and ->

when I have a pointer like:
MyClass * pRags = new MyClass;
So i can use
pRags->foo()
or
(*pRags).foo()
to call foo.
Why these 2 are identical? and what is *pRags?
Thank you
Why are these two identical?
They are equivalent because the spec says they are equivalent. The built-in -> is defined in terms of the built-in * and ..
What is *pRags?
It is the MyClass object pointed to by pRags. The * dereferences the pointer, yielding the pointed-to object.
For more information, consider picking up a good introductory C++ book.
In addition to the other answers, the '->' is there for convenience. Dereferencing a pointer to an object every time you access a class variable for function is quite ugly, inconvenient, and potentially more confusing.
For instance:
(*(*(*car).engine).flux_capacitor).init()
vs
car->engine->flux_capacitor->init()
pRags->foo() is defined as syntactic sugar that is equivalent to (*pRags).foo().
the * operator dereferences a pointer. That is, it says that you're operating on what the pointer points to, not the pointer itself.
The -> is just a convenient way to write (*).. and *pRags is the object at the address stored in pRags.
Yes they are identical. -> was included in C (and thus inherited into C++) as a notational convenience.
* in that context is used to dereference a pointer.
Unary * is known as the dereferencing operator. Dereferencing a pointer turns a T* into a T&; dereferencing an object invokes that object type's unary operator* on that object value if one is defined, or gives an error otherwise.
(*pRags) that goes through the pointer pRags and get you whole object, so on that you could use regular dot notation . .
pRags is a pointer of type MyClass. Just like you can have pointers for primitive data types, e.g. int ptr, you can also have pointers to objects and in this case represented by pRags. Now accessing the object "members" is done using the arrow operator (->) or you can use the "." and dereference "*" to access the object's member values. Here a member is a variable inside MyClass. So, foo() would have a definition inside MyClass.

What is the difference between the dot (.) operator and -> in C++? [duplicate]

This question already has answers here:
What can I use instead of the arrow operator, `->`?
(7 answers)
Closed 5 years ago.
What is the difference between the dot (.) operator and -> in C++?
foo->bar() is the same as (*foo).bar().
The parenthesizes above are necessary because of the binding strength of the * and . operators.
*foo.bar() wouldn't work because Dot (.) operator is evaluated first (see operator precedence)
The Dot (.) operator can't be overloaded, arrow (->) operator can be overloaded.
The Dot (.) operator can't be applied to pointers.
Also see: What is the arrow operator (->) synonym for in C++?
For a pointer, we could just use
*pointervariable.foo
But the . operator has greater precedence than the * operator, so . is evaluated first. So we need to force this with parenthesis:
(*pointervariable).foo
But typing the ()'s all the time is hard, so they developed -> as a shortcut to say the same thing. If you are accessing a property of an object or object reference, use . If you are accessing a property of an object through a pointer, use ->
Dot operator can't be overloaded, arrow operator can be overloaded. Arrow operator is generally meant to be applied to pointers (or objects that behave like pointers, like smart pointers). Dot operator can't be applied to pointers.
EDIT
When applied to pointer arrow operator is equivalent to applying dot operator to pointee e.g. ptr->field is equivalent to (*ptr).field.
The arrow operator is like dot, except it dereferences a pointer first. foo.bar() calls method bar() on object foo, foo->bar calls method bar on the object pointed to by pointer foo.
The . operator is for direct member access.
object.Field
The arrow dereferences a pointer so you can access the object/memory it is pointing to
pClass->Field
pSomething->someMember
is equivalent to
(*pSomething).someMember
Use -> when you have a pointer.
Use . when you have structure (class).
When you want to point attribute that belongs to structure use .:
structure.attribute
When you want to point to an attribute that has reference to memory by pointer use -> :
pointer->method;
or same as:
(*pointer).method
The target.
dot works on objects; arrow works on pointers to objects.
std::string str("foo");
std::string * pstr = new std::string("foo");
str.size ();
pstr->size ();
Note that the -> operator cannot be used for certain things, for instance, accessing operator[].
#include <vector>
int main()
{
std::vector<int> iVec;
iVec.push_back(42);
std::vector<int>* iVecPtr = &iVec;
//int i = iVecPtr->[0]; // Does not compile
int i = (*iVecPtr)[0]; // Compiles.
}
It's simple, whenever you see
x->y
know it is the same as
(*x).y
The -> is simply syntactic sugar for a pointer dereference,
As others have said:
pointer->method();
is a simple method of saying:
(*pointer).method();
For more pointer fun, check out Binky, and his magic wand of dereferencing:
http://www.youtube.com/watch?v=UvoHwFvAvQE
The simplest difference between the two is that "->" dereferences a pointer before it goes to look at that objects fields, function etc. whereas "." doesn't dereference first. Use "->" when you have a pointer to an object, and use "." when you're working with the actual instance of an object.
Another equivalent way of wrinting this might be to use the dereferencing "*" on the pointer first and then just use the ".". We skip middleman by using "->".
There are other differences, but the other answers have covered this extensively.
If you have a background in Java this might confuse you, since, in Java, everything is pointers. This means that there's no reason to have symbol that doesn't dereference your pointer first. In c++ however you gotta be a little more careful with remembering what is and what isn't a pointer, and it might be a good idea to label them with the prefix "p_" or simply "p".
The . (dot) operator is usually used to get a field / call a method from an instance of class (or a static field / method of a class).
p.myField, p.myMethod() - p instance of a class
The -> (arrow) operator is used to get a field / call a method from the content pointed by the class.
p->myField, p->myMethod() - p points to a class
The -> operator is used when we are working with a pointer and the dot is used otherwise.
So if we have a struct class like:
struct class{ int num_students; int yr_grad; };
and we have an instance of a class* curr_class (class pointer), then to get access to number of students we would do
cout << curr_class->num_students << endl;
In case we had a simple class object , say class_2016, we would do
cout << class_2016.num_students << endl;
For the pointer to class the -> operator is equivalent to
(*obj).mem_var
Note: For a class, the way to access member functions of the class will also be the same way