Reputation: 197
So, I understand what pointers are, what it means to reference something, and have a vague understanding of this 'heap'. Where I begin to lose my grip on things is when we introduce functions and classes with the use of these concepts, e.g. sending pointers, returning pointers, etc.
If by reference and passing pointers essentially perform the same function, what is the advantage of using one over the other? Both essentially are passing by reference and manipulating the object outside of the called function.
So, by reference:
#include <iostream>
class student{
public:
int semesterHours;
float gpa;
};
void defRefS( student &refS );
void defPointerS( student *Ps );
void defValueS( student cS );
int main()
{
student s;
defRefS(s); //Here,
std::cout << "\nBack in main we have " << s.semesterHours << " hours";
std::cout << "\nBack in main the GPA is: " << s.gpa;
student *Ps = &s;
defPointerS(&s); //And here is where I get confused
std::cout << "\nBack in main we have " << s.semesterHours << " hours";
std::cout << "\nBack in main the GPA is: " << s.gpa;
defValueS(s);
std::cout << "\nBack in main object S has: " << s.semesterHours << " hours";
std::cout << "\nBack in main object S has: " << s.gpa << " GPA\n\n";
}
void defRefS( student &refS ) //Passing by reference to object
{
refS.gpa = 4.0;
refS.semesterHours = 12;
std::cout << "\n------------- Reference Function ------------";
std::cout << "\n\nObject S has: " << refS.semesterHours << " hours";
std::cout << "\nObject S has: " << refS.gpa << " GPA";
}
void defPointerS( student *Ps ) //Passing a pointer to the object
{
Ps->gpa = 5.0;
Ps->semesterHours = 14;
std::cout << "\n\n------------- Pointer Function ---------------";
std::cout << "\n\nNow object S has: " << Ps->semesterHours << " hours";
std::cout << "\nNow object S has: " << Ps->gpa << " GPA";
}
void defValueS( student cS ) //Passing the object by value
{
cS.gpa = 100;
cS.semesterHours = 50;
std::cout << "\n\n------------- Value Function ------------------";
std::cout << "\n\nObject S has: " << cS.semesterHours << " hours";
std::cout << "\nObject S has: " << cS.gpa << " GPA";
}
Passing by reference essentially allows the notation to be similar since, I suppose, in all ways refS
is the s
object. So, this leads to a simple way to manipulate an object using a function.
Passing a pointer is easy enough to understand. It's just a pointer to the object. Although how about this in the above code:
void defRefS( student &refS );
void defPointerS( student *Ps );
void defValueS( student cS );
Are all of these functions only defined to work with the student class? So, these functions are only able to pass reference, pointer, and values of objects to this specific class?
defRefS(s); //Here,
defPointerS(&s); //And here is where I get confused
defValueS(s);
If passing by reference, shouldn't you pass the address of an object? So, for me, it made more since to pass the argument of the pointer function in the reference function.
The function defPointerS
is defined to accept pointers; I'm sending it addresses?
Upvotes: 1
Views: 767
Reputation: 110778
You're getting confused between two uses of the ampersand (&). In one case it is an operator and in the other case it's part of the type of a declaration.
int x = 5;
int* y = &x; // (1) Here it's an operator
int& z = x; // (2) Here it's part of the type of y
In line (1) above, we are declaring and defining a variable called y
which is of type pointer to int
. This means the variable y
should contain the address of a variable of type int
. To get the address of a variable, you use &
as an operator. Thus, &x
is the address of x
and we're storing it in a pointer. y
is now a pointer to x
.
In line (2), we are defining a variable called z
which is of type reference to int
. Since we bind x to this refernece, this means we can use z
as another name for x
. Modifying z
will modify x
(and also the value that y
points to!).
So when you have a function that takes a pointer, like void func(int* p)
, you need to pass it the address of an int. To do this, you will either pass a pointer directly or take the address of an int
:
int x = 5;
func(&x);
If you have a function that takes a reference, like void func(int& r)
, you only need to pass it an int
. The reference will refer to the same int
.
int x = 5;
func(x);
These can be used in similar ways: to pass an argument in to a function so that the function can modify it or to avoid copying. However, a pointer argument also allows you to pass a null pointer in to the function. This doesn't work with a reference because a reference must always be bound to something. In addition, a reference cannot be rebound to a different object once it has been bound.
References are generally much more convenient and don't rely on C-style pointer manipulation. In C++, you normally want to use a reference whenever you can, and a pointer if you have to. See the C++ FAQ for details.
Upvotes: 2
Reputation: 2194
I'm guessing you're just starting out in C++. Don't worry about the heap, it's a lower level concept that you'll learn about later. If you are really interested, the new
operator and malloc
allocate memory on the heap (new actually invokes the constructor of the object as well, giving you a a dynamic object). You can think of it as just a big space where you can put stuff that you want later).
About pointers and references, they are interchangeable most of the time (as you figured out). It just depends on how you want to structure your code.
In C++, pointers are everywhere, and people generally pass pointers rather than pass by reference. One of the reasons pointers are used more frequently is because of how dynamic memory allocation works (the new
operator or malloc
) -- it returns a pointer -- and you do a lot of it. So generally you'd be doing work on an object via the pointer you are given.
The rare occasions where you absolutely must use references is in a copy constructor or in defining operators.
I probably missed a few cases, but this is the gist of it.
Upvotes: 2
Reputation: 4459
For starters see What are the differences between pointer variable and reference variable in C++?.
When passing a variable by reference, you can think of it as implicitly taking the address, so you don't have to write the &, but it's still doing it for you (this is why you will get an error if you pass a constant like "5" for a reference parameter). It also implicitly dereferences it inside the function, so you don't have to write "*" either.
"The function defPointerS is defined to accept pointers; I'm sending it addresses?" A pointer is an address (or more properly, is a variable that stores a memory address value).
"So, these functions are only able to pass reference, pointer, and values of objects to this specific class?" These types indicate that if you try to pass an instance of another class to this function, you will receive a compiler error. However C++ does not strongly enforce type safety and you can circumvent it and force it to pass pointers to other types of objects with "reinterpret_cast". In most cases, this will not work.
Upvotes: 0
Reputation: 2914
what is the advantage of using one over the other?
Good reason to use a reference for passing input parameter for a function : a reference never can be NULL, so you don't need to check is the pointer points anywhere.
Good reason to use a pointer for passing input parameter for function: you can use pointer arithmetic, so you can pass arrays (which is not recommended in c++). So better to stick to references in most cases.
If passing by reference, shouldn't you pass the address of an object? - No, you pass an object as it is. An ampersand near parameter means that parameter takes reference to the object without copying.
The function defPointerS is defined to accept pointers; I'm sending it addresses? - the operator "&" when applying to r-value produces a pointer to an object.
Upvotes: 1
Reputation: 42133
When you have student s;
variable and you want to pass it to function f
that takes argument of type student
(passing by value) or student&
(passing by reference), you just call f(s)
. If you pass s
by value, then copy of s
is created and you work with copy of s
in the body of function. If you pass it by reference, you work directly with the object s
. Reference can not be NULL which is great advantage in many situations.
When type of this argument is student*
(also passing by reference), you call f(&s)
since pointer needs to be initialized with address it will point to.
You should also check: Pointer vs. Reference
Upvotes: 0
Reputation: 20282
When you use character &
in function/type definition (like in void defRefS( student &refS );
or student &refS
) - you're defining a reference. The value would be a reference.
When you use the same operator (i.e.: the same character &
) on an object (a variable), you're getting the address of that particular object (like in student *Ps = &s;
or in defPointerS(&s);
). The value would be a pointer.
Still confused? Then don't read the next sentence. Operator &
is also a bitwise-AND, when in statement, for example 0x1 & 0xFF
yields 1. The return value would be an integer in the size of the biggest integer in the statement.
Upvotes: 1