In a recent assignment for a data structures class, we we're expected to use this "*&" in a function parameters list. I am having trouble finding info on why this exists, and even what it does. Is it standard practice to use this?
Here's a code snippet
template <class T>
Thing <T> * action(const T &dataIn, Thing <T> *& thingIn)
{
if(thingIn == NULL)
{
Node <T> *newThing = new Thing <T> (dataIn);
newThing->ptr = thingIn;
thingIn= newThing ;
return(newThing );
}
}
I guess another part of my question is, why use "*&" at all couldn't you just send the pointer?
It is used for a reference type pointing to a pointer
Example
int *&ref = ptr;
in the above example, ref is a reference to an int pointer ptr
which then can be passed in to a function
function(int *&ref)
fun(int x)
fun takes an int value
fun(int* x)
fun takes an int pointer by value
fun(int& x)
fun takes an int by reference
fun(int*& x)
fun takes an int pointer by reference - the value of the pointer to x as seen by the caller can be changed by fun
If you have a structure for example like
struct A
{
//...
};
then a function parameter can look like
void f( A * &pa );
In this declaration A * means pointer type and & means that this pointer is passed to the function by reference.
Compare these two code snippets
void f( A * &pa )
{
pa = new A();
}
//...
A *p = nullptr;
f( p );
After calling the function the variable p will have the address of the allocated memory in the function because it was passed to the function by reference.
If the function would be declared like this
void f( A * pa )
{
pa = new A();
}
//...
A *p = nullptr;
f( p );
then after calling the function the pointer p would not be changed because the function deals with a copy of the pointer.
let's look into this:
void fun( int i );
we pass parameter by value, it means function can use int i but cannot change variable that is used to pass that value:
void fun( int i ) { i = 123; }
int main()
{
int j = 0;
fun( j );
std::cout << j << std::endl; // j is still 0
}
on another side when we use refernce, variable would be changed:
void fun( int &i ) { i = 123; }
int main()
{
int j = 0;
fun( j );
std::cout << j << std::endl; // j is 123 now
}
if you understand this concept you should be able to undestand more complex types, just use typedef or more modern using:
typedef char * pchar;
fun( pchar &p );
fun( char *&p ); // this is the same as before
you can actually use it in program or at least in your mind, that should simplify your understanding that a pointer is the same variable as anything else. It also helps to understand other complex types like pointer to pointer etc.
In a recent assignment for a data structures class, we we're expected to use this "*&" in a function parameters list. I am having trouble finding info on why this exists, and even what it
does.
C++ declarations can be read from right to left. It's a reference to a pointer.
Is it standard practice to use this?
Not really. See below.
I guess another part of my question is, why use "*&" at all couldn't you just send the pointer?
A reference allows you to modify the object which is being referenced.
A pointer is an object. So a reference to a pointer allows you to modify a pointer. Modifying a pointer means to make it point somewhere else. So if you take a *& in a function, then it means that the function can change where the pointer outside of the function points to.
Changing the destination of a raw pointer is not something you do very often in C++, but as always, it depends on your application domain.
Changing the destination of an existing pointer certainly feels more like C-style programming, and there are no references in C. In C, you would use ** instead of *& to accomplish this, and pass a pointer to a pointer, accordingly.
Related
I was reading some code online and I found them passing node*& instead of just node* and I didn't really understand why.
My understanding was that you pass parameters by reference when you either want your changes to sort of propagate back to the original variable outside of the function (which a pointer would do) or if you wanted to avoid copying the object every time the function is called to avoid the copying overhead which is also what a pointer would do.
Am I wrong or are they? If I am, what am I getting wrong?
When you pass by reference, it acts as an alias -- be it a normal object or a pointer.
To explain in detail, let's consider below declaration:
int i = 10, *pi = &i;
Now following are the different meanings of passing and using them in various functions:
void foo_pointer (int* p) // 1st (can pass `&i` and `pi`)
{
*p = 0; // modifies `i`
p = nullptr; // no effect on `pi`
}
void foo_pointer_reference (int*& p) // 2nd (can pass `pi`)
{
*p = 0; // modifies `i`
p = nullptr; // modifies `pi`
}
void foo_const_pointer_reference (const int*& p) // 3rd (can pass `pi`)
{
*p = 0; // ERROR
p = nullptr; // modifies `pi`
}
void foo_const_pointer_const_reference (const int* const& p) // 4th (can pass `&i` and `pi`)
{
*p = 0; // ERROR
p = nullptr; // ERROR
}
From above examples, you can see that another use case of declaring T*& as a function parameter is that, it restricts only pointer passing to that function. i.e. in above case &i is not allowed to be passed to 2nd and 3rd functions. However pi can be passed to all the functions.
You can pass a pointer by reference if you want the function you call to change the pointer to point to something else.
Other than that, I don't see any valid reason (but that is sometimes a valid reason).
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What are the differences between pointer variable and reference variable in C++?
This is confusing me:
class CDummy
{
public:
int isitme (CDummy& param);
};
int CDummy::isitme (CDummy& param)
{
if (¶m == this)
{
return true; //ampersand sign on left side??
}
else
{
return false;
}
}
int main ()
{
CDummy a;
CDummy* b = &a;
if ( b->isitme(a) )
{
cout << "yes, &a is b";
}
return 0;
}
In C & usually means the address of a var. What does it mean here? Is this a fancy way of pointer notation?
The reason I am assuming it is a pointer notation because this is a pointer after all and we are checking for equality of two pointers.
I am studying from cplusplus.com and they have this example.
The & has more the one meanings:
1) take the address of a variable
int x;
void* p = &x;
//p will now point to x, as &x is the address of x
2) pass an argument by reference to a function
void foo(CDummy& x);
//you pass x by reference
//if you modify x inside the function, the change will be applied to the original variable
//a copy is not created for x, the original one is used
//this is preffered for passing large objects
//to prevent changes, pass by const reference:
void fooconst(const CDummy& x);
3) declare a reference variable
int k = 0;
int& r = k;
//r is a reference to k
r = 3;
assert( k == 3 );
4) bitwise and operator
int a = 3 & 1; // a = 1
n) others???
To start, note that
this
is a special pointer ( == memory address) to the class its in.
First, an object is instantiated:
CDummy a;
Next, a pointer is instantiated:
CDummy *b;
Next, the memory address of a is assigned to the pointer b:
b = &a;
Next, the method CDummy::isitme(CDummy ¶m) is called:
b->isitme(a);
A test is evaluated inside this method:
if (¶m == this) // do something
Here's the tricky part. param is an object of type CDummy, but ¶m is the memory address of param. So the memory address of param is tested against another memory address called "this". If you copy the memory address of the object this method is called from into the argument of this method, this will result in true.
This kind of evaluation is usually done when overloading the copy constructor
MyClass& MyClass::operator=(const MyClass &other) {
// if a programmer tries to copy the same object into itself, protect
// from this behavior via this route
if (&other == this) return *this;
else {
// otherwise truly copy other into this
}
}
Also note the usage of *this, where this is being dereferenced. That is, instead of returning the memory address, return the object located at that memory address.
Well the CDummy& param that is declared as a parameter of the function CDummy::isitme is actually a reference which is "like" a pointer, but different. The important thing to note about references is that inside functions where they are passed as parameters, you really have a reference to the instance of the type, not "just" a pointer to it. So, on the line with the comment, the '&' is functioning just like in C, it is getting the address of the argument passed in, and comparing it to this which is, of course, a pointer to the instance of the class the method is being called on.
I recently saw a function that is being declared as:
void func(type* ¶m);
I already know the difference between type* param and type& param. How does the above differ from them? And when to use this? Is it advisable to do this?
The above will be able to modify not only the pointed object, but also the pointer in itself. As an example, consider the below code:
void func(int*& ptr) {
*ptr = 1;
ptr = 0;
}
int main() {
int x = 0;
int* y = &x;
func(y);
}
At the end of the execution, x has value 1 and y is 0 (as you can see).
Notice that for the sake of the example I've used 0 as a null pointer, but if you are using C++11 you should probably use nullptr instead (which does not have an overloaded operaror<< for std::ostream).
This concept can possibly be assimilated by taking a look at the following code:
template<class Type> using ptr = Type*;
ptr<int>& x;
or
std::unique_ptr<int>& x;
In these examples, x is a reference to a type (ptr<int> and then std::unique_ptr<int>), which just so happens to be a pointer/class with pointer semantic (operator* and operator->).
A possibly interesting digression can be made on the position of a const qualifier in the pointer. Consider these two instances:
void func(const int*& ptr)
void func(int*const& ptr)
Their meanings are:
pointer by reference to a constant int.
pointer by constant reference to an int.
And following the above analogy with ptr they would be:
ptr<const int>&
ptr<int> const&
Therefore the first will fail to execute *ptr = 1 in the body of the function (because the int is constant), but will happily execute ptr = 0.
The second will behave conversely, allowing *ptr = 1 (because the pointed int is not constant), while disallowing ptr = 0 (because the pointer is constant).
Of course, in the case of:
void func(const int*const& ptr)
which in the ptr analogy would be ptr<const int> const&, both of them wouldn't be allowed.
And when to use this? Is it advisable to do this?
Like every feature, you'll find its usefulness when you'll need it. But just as a general idea, some people used it to reset the pointer after freeing a dynamically allocated resource (I'm not recommending this, see below).
Let's take this example:
free_my_int(int*& ptr) {
delete ptr;
ptr = nullptr;
}
int* x = new int(42);
free_my_int(x);
At the end of the execution, x would be correctly freed and the pointer automatically set to nullptr (null pointer). This was done to prevent ugly segmentation faults or "pointer freed has not been allocated" error messages caused by a missing ptr = nullptr.
But with C++11 and C++14 there is very little use of pointers and even less of reference to pointers. Most of the things pointers where used for are not replaced with other standard construct (see std::optional, std::unique_ptr, std::shared_ptr or std::reference_wrapper for example).
Let's compare all three options:
void func(type* param); // 'param' is a 'type*' variable
void func(type& param); // 'param' is a reference to a 'type' variable
void func(type*& param); // 'param' is a reference to a 'type*' variable
void func(type* param)
{
type x;
...
param = &x;
// Argument 'param' is regarded as a local variable in this function,
// so setting 'param = ...' will have no effect outside this function
}
Of course, if you do *param = ..., then it will effect the contents of the memory pointed by param. And you can also do param[5] = ... for example, and effect other areas within that memory space.
void func(type& param)
{
type x;
...
param = x;
// Argument 'param' is regarded as a reference to a variable outside this
// function, so setting 'param = ...' will effect the referenced variable
}
Here, you will only change the referenced variable itself, so it's safer than declaring the function as void func(type* param), and then pass the address of type param by calling func(¶m).
void func(type*& param)
{
type x;
...
param = &x;
// Argument 'param' is regarded as a reference to a variable outside this
// function, so setting 'param = ...' will effect the referenced variable
}
This is similar to declaring the function as void func(type** param), and then pass the address of type* param by calling func(¶m), but again, it is safer for the same reason mentioned above.
int y=5;
int *yPtr = nullptr;
yPtr = &y;
I understand that the pointer stores the address of y. and calling *yPtr dereferences y.
If I have a call to the void function:
int main()
{
int number = 5;
function( &number );
}
void function( int *nPtr)
{
*nPtr = *nPtr * *nPtr;
}
if the function takes a pointer as argument, how can the call to the function use an address?
I understand that nPtr stores addresses but why couldn't it be defined as.
void functions (int &ref)
{
ref = ref * ref;
}
My main question would be: Why does a function receiving an address argument need a pointer parameter to receive the address?
By using a pass-by-reference parameter, you force your function not the copy the value of the parameter itself, instead, to use the actual variable you provide. So, for a more clear view, see below:
void function( int number )
{
cout << number;
}
function( myInt ); // function will copy myInt, into its local variables stack
but, by using the pass-by-reference method, like this:
void function ( int & number )
{
cout << number
}
function( myInt ); // function will not copy myInt into its local variables stack, instead, it will use the already existent myInt variable.
There is no difference in how to compiler will work with pass-by-pointer and pass-by-reference parameters. Instead, the call of your function will look like so:
void function_p( int *number )
{
cout << *number;
}
void function_r( int & number )
{
cout << number;
}
// and the calls
function_p( &myInt ); // it is required to use address-of operator here
function_r( myInt ); // the effect will be the same, but with less effort in writing that address-of operator
In C++11, programmers started to use pass-by-reference method, in general, ordinarily because it has an easier writing "template".
To complete the answer to your question, the * and & operators refer only to the type of the parameter, so that they create compound types. A compound type is a type that is defined in terms of another type. C++ has several compound types, two of which are references and pointers.
You can understand that they only affect the type of a variable (in our case, a parameter), by writing them in a proper way:
int* p1; // we will read this: pointer p1 points to an int
int* p2 = &var1; // we read this: pointer p2 points to int variable var1
int var1 = 12;
int& ref1 = var1; // and we read this: ref1 is a reference to var1
You can generally consider references represent a different for the same block of memory.
you did mean
void functions (int &ref)
{
ref = ref * ref;
}
that's how you use refs, avoiding all the '*'s of pointers syntax
This is another of those quirky things of C++. Passing by reference is not the same as passing a pointer. When you do something like
void functions (int &ref)
You can pass an actual variables into functions (rather than pointers to them) like
int a = 12;
functions(a);
And inside the function you have no need to dereference. Notice that you are passing by reference, rather than passing a reference.
When you pass a reference, or pointer to something, you use star as such
void function( int *nPtr)
And thus you have to dereference with a *
Note also that you get the reference to a variable (or constant) by putting & in front of it, but you declare a reference or pointer by putting a * in front of it. At the same time, you dereference a pointer also by putting a * in front of it.
I would pass T*& pointer, when I am intending to change the pointed value inside the function:
void foo(char *&p)
{
p = (b == true)? new char[10] : 0;
}
But I am not able to get what is the use case for T* const& kind of pointer (since that pointer is not changeable)? I mean why should not I pass simply T* const ?
void foo(char* const &p); // p is not changeable
void foo(char* const p); // p is not changeable
You would use a T* const & as a parameter if the value of the pointer object might be changed by something external to your function and you wanted to be able to observe changes to the value of the pointer object or if you wanted to store a reference or pointer to the pointer object for later reading.
A T* parameter (equivalent to T* const as a function parameter) just gives you a copy of the pointer object, a snapshot of its value when it was passed to your function.
void foo( char* const& ptr )
{
char* p1 = ptr; // initial value
global_fn(); // ptr might be changed
char* p2 = ptr; // new value of ptr
}
vs
void foo2( char* ptr )
{
char* p1 = ptr; // initial value
global_fn(); // ptr can't be changed, it's local to this function
char* p2 = ptr; // will be the same as p1
}
Technically, even the function itself might change the value of the pointer to which it is passed a reference.
E.g.
char* p;
std::ptrdiff_t foo( char* const& ptr )
{
++p;
return p - ptr; // returns 0, would return 1 if the parameter was by value
}
int main()
{
char test[] = "Hello, world!";
p = test;
foo( p );
}
The difference is realistically nil. const references are used to prevent copying of expensive-to-copy or, in generic code, uncopyable types, but since pointers are trivial, it's negligible and you may as well take by value.
I think a simpler example would illustrate the point that Charles Bailey is making. Let's remove the issue of the pointer part of it, because for this question it is irrelevant. So your question basically becomes:
void foo(const int &p); // p is not changeable
void foo(const int p); // p is not changeable
Do you see more clearly how it works? Yes, the local variable "p" cannot be assigned to in both cases. And yes, neither piece of code will affect the variable in the calling scope. But in the former example p could be a reference to a variable (non-const) int that can be changed while the latter is an argument passed by value which could not be changed. (Actually the const in the second example has no effect on anything outside the function, so it is kind of superfluous. Same with the second example in the question.)