It is common to have either a pointer or a reference to a struct (or class). As you learned previously, you can select the member of a struct using the member selection operator (.):
1 2 3 4 5 6 7 8 9 10 |
struct Person { int age{}; double weight{}; }; Person person{}; // Member selection using actual struct variable person.age = 5; |
This syntax also works for references:
1 2 3 4 5 6 7 8 9 10 |
struct Person { int age{}; double weight{}; }; Person person{}; // define a person // Member selection using reference to struct Person &ref{ person }; ref.age = 5; |
However, with a pointer, you need to use the arrow operator:
1 2 3 4 5 6 7 8 9 10 |
struct Person { int age{}; double weight{}; }; Person person{}; // Member selection using pointer to struct Person *ptr{ &person }; ptr->age = 5; |
The arrow operator does the same as an indirection followed by the . member selection operator
1 2 3 |
(*ptr).age = 5; // same as ptr->age = 5; |
Note that indirection through the pointer must be enclosed in parentheses, because the member selection operator has a higher precedence than the indirection operator.
The arrow operator is not only easier to type, but is also much less prone to error because the indirection is implicitly done for you, so there are no precedence issues to worry about. Consequently, when doing member access through a pointer, always use the -> operator instead of the . operator.
Rule
When using a pointer to access the value of a member, use operator-> instead of operator. (the . operator)
The member selection operator is always applied to the currently selected variable. If you have a mix of pointer- and normal member variables, you can see member selections where . and -> are mixed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#include <iostream> #include <string> struct Paw { int claws{}; }; struct Animal { std::string name{}; Paw paw{}; }; int main() { Animal puma{ "Puma", { 5 } }; Animal* pointy{ &puma }; // pointy is a pointer, use -> // paw is not a pointer, use . std::cout << pointy->paw.claws << '\n'; return 0; } |
![]() |
![]() |
![]() |
Here's a question, imagine we have a struct that have a pointer in it. how do you access that pointer inside the struct.what i mean by that is how do you apply indirection throught that pointer.
// pointy is a pointer, use ->
// paw is not a pointer, use .
std::cout << << '\n';
is pointy->paw.claws instead of pointy->paw.age
Thanks
u are referencing "age" member in the last example but "age" member doesn't even exist....
Hey,
I was confused about nested elements. I was able to figure it out but would it be good to add a note in this section about the fact that after -> is just shorthand for (*x). and that you would continue using . to get to nested elements. Unless the nested element is also a pointer, in which case you would use ->.
Sorry if that is confusing. I just wanted to point out that someone might not realize this is proper: pointer->object.pointer2->object
I've updated the lesson to clarify when to use -> or .
Thanks for pointing out your confusion!
I see that we are all of sudden only using the copy assignment operator for references and pointers to member selection. Can we use uniform/brace initialization here as well?
Yes please, I updated the lesson.
Shouldn't the last line of this lesson "Rule: When using a pointer to access the value of a member, use operator-> instead of operator. (the . operator)" be placed in a beautiful green Rule box?
So in the last unit, you mentioned to use references when possible instead of pointers. I find it easier to do the following.
Then to use pointers and have to worry about possible errors or things like that. Also becuase since it
is a reference isn't it more memory efficient?
Anyways I am just wondering what to prefer, pointers or references or what do you prefer? I mean I will still learn them both the best I can and obviously, they are different and pointers can do many things references cant like dynamically allocating memory or like scanning words or cool things like that, but when it doesn't necessarily matter which do I prefer?
Nvm I think I got a good idea on which to prefer. lol
As a programmer you shouldn't care how memory efficient what you do is, unless you have a good reason to. That's called over-optimizing your code. You should privilege making your code readable and maintainable rather than optimized ; and if you later notice some inefficiencies harming the execution of your code, only then should you optimize it. I'm not expert on C++ compilers but I would not be surprised if references behave exactly like pointers when it comes down to generating machine code on some cases.
I guess the preferred usage of references compared to pointers is that references give more guarantees than pointers. You won't have any dangling pointer or memory leak with references. This comes at the cost of functionality - you can do less things with references than you can with pointers.
A few remarks on your code, first of all I would really indent it. I know it's just a tiny example, but if you start not indenting your code in small examples, this opens the door to being lazy on your bigger codes. And the lack of indentation can make a code very unreadable.
Also I would not do the following (but it's a matter of style):
If you feel like you need to express in a comment what your variable means, then your variable doesn't have a good name. Just call your variable `username`. Or `name` if you want something short.
Just a quick note -- dangling references are a real thing. For example, a function that returns a reference to a local variable will pass back a dangling reference to the caller.
These tutorials are giving me such an incredible proper foundation for understanding what I write and why. I'd learnt bits and pieces of C++ before, but now I really feel like I'm writing good-quality code that conforms to best practices, is efficient and safe, and most of all that I fully understand and have control over!! For example, I finally understand the nuances and best uses for pointers, references, and their syntax, which always held me back before, hence why I'm writing this comment here.
Again, I can't express how grateful I am for these well-written and useful these tutorials are. Thanks so much Alex and co!!!!
You're welcome. Thanks for visiting!
Hi, while doing the exercize 2 of the quiz chapter 6, I noticed that this code won't compile
Apparently using the -> operator is a mistake and I just have to change the operator to the dot operator and it works as expected.
But could you explain while the -> operator is a mistake here since listStudent is a pointer ? IS it because i'm indirectly dereferencing the array with the
subscript operator [] ? Thanks in advance
is a Student*
is a Student
To avoid confusion, I suggest using
for array parameters.
There's a slight typo, "parenthesis" should be "parentheses".
Fixed! Thanks!
Hi,
Using the following code:
it builds fine and runs but won't let me input the team name. Am I missing something? I used std::getline because some tams have names with white spaces in and std::cin stops at white space.
Hi Nigel!
@std::cin::operator>> leaves a '\n' in the input stream, @std::getline only reads up to the next '\n'. You need to @std::cin.ignore after using @std::cin::operator>>
Oops! Of course it does. The following is better and works correctly:
Thank you
* Line 19: Should be const reference
* Line 38: You know
* Line 36: Use @std::numeric_limits<std::streamsize>::max(). See the documentation of @std::cin.ignore
* You're using the same name style for types, functions, and variable. This will get confusing.
Ok, thx for putting this together for me: using (.) operator and (->) selection operator on the object...
Gosh hate to post yet another question on this one chapter but, here goes: why is C++ configured so that we use aliases often. Why do we use aliases instead of original values? What function does the alias serve?
If by "aliases" you mean references, we use (const) references wherever we can because they prevent values from being needlessly copied (especially when transferring an argument to a function parameter).
I understand that -- you have some really good teaching pts. there. What tripped me up was the insistence of some to call references aliases. I need to disambiguate: e.g.
"When a reference is created, you must tell it which variable it will become an alias for."
"A reference variable is an alias, that is, another name for an already existing variable."
These are from "teaching sites".
So naturally I thought maybe I missed a teaching point.
Rob,
I'm just a fellow student, but hopefully this helps to clarify...
Hi Alex
regarding
is &ref an alias for object test?
Is &ref referencing the address of test?
for e.g. [code]A * ptr = new A()
, deleting is done by deleting the pointer? ptr
for Object object, object.a (etc.), how is it destroyed? Delete only works on the heap
Reviewing some here.
In Test &ref = test, ref is an alias for object test.
For A *ptr = new A(), you delete this by simply calling "delete ptr". We'll talk about what happens when objects are deleted (e.g. destructors) in chapter 8. And yes, delete only works with dynamically allocated memory, which means it only works on the heap.
Alex loving your tutorial! thank for everything
so like ... pointers hold memory address only and to get the value of a memory address that the pointer is pointing to you add * before the pointer variable.
but can anyone explain why ptr->age = 5; ?
i mean it seems like ptr now is a reference to the value of the memory address. it has become what data type the memory address is holding. why is it not *ptr->age = 5; ?
ptr->age is a "shortcut" for (*ptr).age. Operator-> does an implicit dereference (for convenience).
That makes perfect sense thanks
Thank you for everything Alex. You have brought me from total noobiness to the point where I can output dynamically allocated 2d arrays of chars in the console. I have recommended your tutorials to a friend and look forward to reading more.
That's great! Thanks for visiting.
Alex,
Isn't the -> operator called the arrow operator? And the . operator called the dot operator? Since you didn't mention them I was wondering if they were colloquial names. Then, in the last sentence:
> ... always use operator-> instead of operator.
^ dot operator or full stop? :D
IMHO you should at least say "... always use the -> operator instead of the . operator." if you're not using the terminology. Put the symbol before 'operator'.
That last sentence also deserves a rule status, doesn't it? Repeat in italics! :)
. is often called "dot" and -> is often called "arrow", but these are colloquial names. I've updated the article based on your other suggestions. Thanks!
Thank you Alex, clear as always.
Hi Alex I have 2 questions. In the code below dereference occurs as a step if the -> is not used. What does the dereferencing produce? Literally what value/object is a result of dereferencing. (full code at bottom)
1)
I've lost my way. What does the & do in this line?
2)
Full code:
1)
(*n_ptr).value_1 = 5;
is the same asn_ptr->value_1 = 5;
, so you're just assigning the value of 5 to the value_1 member of mem_vars.2) In this context, & gets the address of mem_vars, so the pointer can point to it. Remember that pointers hold addresses.
This is covered in lesson 6.10.
Basically, you say that the pointer points to a constant address, NOT that it points to a constant value. The following lines are OK:
const int *constPointer = &value; // fine!
The value of the pointer cannot be changed; but the pointer can be assigned to another address. Or:
const int *const constPointer = &value; // Also fine!
Here, you cannot change the value of the pointer OR the address it points to.
i love you Alex.
every time i stuck and want to understand some thing deeply,i just come here... and i am sure i will get what i want.
you must write all those heavy books.
not these stupids called writers that just make things hazier!
Brain overflow. Need to take a rest :)
What cannot be done using references in C++. Can we have array of references just like array of pointers?
There are a few things you can't do with references (this is not an exhaustive list):
* You can't dynamically allocate memory using references.
* You can't have a null reference.
* You can't change where a reference points (they're implicitly const).
* You can't have a pointer to a reference (because a reference isn't considered a real object in C++).
* You can't have an array of references (because an array is essentially a pointer, and you can't have a pointer to a reference).
I'm sure there are others.