Passing reference variables to function - c++

Why are reference variable are considered as pointer in parameter passing?
int x;
void fun(&x);
void fun(int* y)
{
------some code----
}
Here, reference of variable x is passed to fun() function. Local variable y in fun() contains reference of variable x but y is declared as pointer. Why?

You're mistaken &x is not a 'reference variable'. It is a pointer to x, & is the address-of operator, which returns the address (i.e. a pointer) of whatever argument it's given.
It's confusing because & is used to mean a reference in type declarations but it's meaning in expressions is different.
For example
int x;
int& y = x; // here & means reference because 'int&' is a type declaration
int* z = &x; // here & means address-of because '&x' is an expression

void fun(&x);
in this line &x is "not reference variable", that is address of x variable.
Example:
int y ;
int &z = y; // here &z is reference variable(a reference must initialized when it is created)

Here: void fun(&x);
You are passing the address (and not a reference) of variable x to void fun(int* y).
Since int* y is a pointer, it then points to the address of x.

Related

Creating a reference variable in two statements

int x;
int& foo = x;
// foo is now a reference to x so this sets x to 56
foo = 56;
How can I split the statement int& foo = x; into two statements?
By splitting, I mean using two statements such as in the below example:
int y;
int* ptr = &y;
I can split the int* ptr = &y into two statements declaring the pointer first.
int* ptr;
ptr = &y; //then assigning the pointer to point to y
How to do a similar thing to a reference? I'm looking also for an explanation on why or why not?
No, this can not be done, there are only a few cases where an intializer for a reference can be omitted, from the draft C++ standard section 8.5.3 [dcl.init.ref]:
The initializer can be omitted for a reference only in a parameter
declaration (8.3.5), in the declaration of a function return type, in
the declaration of a class member within its class definition (9.2),
and where the extern specifier is explicitly used. [ Example:
int& r1; // error: initializer missing
extern int& r2; // OK
—end example ]
As to why we find the following rationale for why references are not resettable from The Design and Evolution of C++:
It is not possible to change what a reference refers to after
initialization. That is once a C++ reference is initialized it cannot
be made to refer to a different object later; it cannot be re-bound. I
had in the past been bitten by Algol68 references where r1=r2 can
either assign through r1 to the object referred to or assign to a new
reference value to r1 (re-binding r1) depending on the type of r2. I
wanted to avoid such problems in C++.
You just can't. Consider the reference like a const pointer:
int& foo = x is the same as int * const foo = &x.
That's why you can't re-assign a reference, or declare a new one without a value.
No you can't.
A possible workaround is to use std::boost::optional<T&> or simply T*
int x;
boost::optional<int&> foo; // or int* foo = nullptr;
foo = x; // foo = &x;
// foo is now a 'reference' to x
*foo = 56; // now, we have x == 56
There is such a thing as an empty pointer, but there is not such a thing as an empty reference. A reference has to have something that it refers to. It must be initialized.
int& r; // error
This is one of the main differences between a pointer and a reference, and is one of the reasons to potentially prefer taking a reference argument (must be valid) over a pointer argument (can be null).
You have no way to do this.
Reference should be constant so you may only initialize it.
No, a reference must be initialised as it is declared to support the guarantee that there are no references that point into nowhere.

Is a variable after initialization a reference?

In this example, what is x? Is it a reference?
int x = 5; //What is x?
int &y = x; //This is an alias for x
int *z = &x; //This is a pointer to x
No x is int variable. y is reference to int (x) and z is pointer to int (x).
You are getting confused.
x is an int variable. It is a concrete object of type int.
y is a reference. It is basically a pointer that's already deferenced for you. You can treat it as if it was x.
z is a pointer to x. It holds the memory address of x, so you can access it if needed. It needs to be deferenced.
You can understand the "non-reference variable" as something from which a reference can be taken. Every variable "consists of" a "reference", which is a language interface for it, and the internal representation, which is a piece of memory that holds its value.
If you create a "reference variable" and initialize it with some normal variable, you will create a new "reference", that is, another "language interface" (a separate name) that is pinned into the same internal representation as the source variable. Note that it's bound to the internal representation of the variable, not the variable itself.
The pointer simpy points to the representation itself. The pointed type is a potential type of the "reference" (that is, the language interface to the variable), if you do "pointer dereference" (use *z expression).
The actual type of an expression of the variable 'x' is 'int&'. If you pass it to a function or assign to another variable (in C++ they are both understood as "function call"), there will be a conversion from int& to int. Note, however, that if you pass it to a function where a template-parametrized type is used on that position, and it will be specified as "T x" (not "T& x"), then T will be picked up as 'int' (not int&), no matter if you passed an immediate int value or a variable of type int.
X is an integer variable.
int &y =x; // is treated by compiler as int *const y = &x
So reference operator is used as name aliasing for variables and reduces the complexity of dereferencing the value by developer.

declaration of reference and pointer in c++

For example, if F is a reference to an integer, where the reference is not permitted to be pointed to a new object once it is initially pointed to one.
Can I write to declaration like: const int & F?
I am confused about reference and pointer, because they both represent the address of something, but we always write parameter use reference as: const & F, I understand that this is to reduce the copy and does not allow others to change it, but are there any other meanings? and why do we need "const" after a function declaration like: int F(int z) const; this const makes the return type const or everything in the function const?
One more example,
void F(int* p)
{
p+=3;
}
int z=8;
F(&z);
std::cout<<z<<std::endl;
What is the output for z since z is a reference, and I pass it as a pointer who points to an integer.Increasing p by 3 just makes the address different and does not change its value?
Just a first pass at some answers - if anything is unclear please comment and I'll try to elaborate.
int a = 3;
declares an integer, a, with the initial value 3, but you are allowed to change it. For example, later you can do
a = 5; // (*)
and a will have the value 5. If you want to prevent this, you can instead write
const int a = 3;
which will make the assignment (*) illegal - the compiler will issue an error.
If you create a reference to an integer, you are basically creating an alias:
int& b = a;
, despite appearances, does not create a new integer b. Instead, it declares b as an alias for a. If a had the value 3 before, so will b, if you write b = 6 and print the value of a, you will get 6 as well. Just as for a, you can make the assignment b = 6 illegal by declaring it as const:
const int& b = a;
means that b is still an alias for a, but it will not be used to assign a different value to a. It will only be used to read the value of a. Note that a itself still may or may not be constant - if you declared it as non-const you can still write a = 6 and b will also be 6.
As for the question about the pointers: the snippet
void F(int* p) {
p += 3;
}
int z = 8;
F(&z);
does not do what you expected. You pass the address of z into the function F, so inside F, the pointer p will point to z. However, what you are doing then, is adding 3 to the value of p, i.e. to the address that p points to. So you will change to pointer to point at some (semi)random memory address. Luckily, it's just a copy, and it will be discarded. What you probably wanted to do, is increment the value of the integer that p points to, which would be *p += 3. You could have prevented this mistake by making the argument a int* const, meaning: the value of p (i.e. address pointed to) cannot be changed, but the value it points to (i.e. the value of z, in this case) can. This would have made *p += 3 legal but not the "erroneous" (unintended) p += 3. Other versions would be const int* p which would make p += 3 legal but not *p += 3, and const int* const` which would have allowed neither.
Actually, the way you have written F is dangerous: suppose that you expand the function and later you write (correctly) *p += 3. You think that you are updating the value of z whose address you passed in, while actually you are updating the value of a more-or-less random memory address. In fact, when I tried compiling the following:
// WARNING WARNING WARNING
// DANGEROUS CODE - This will probably produce a segfault - don't run it!
void F(int* p) {
p += 3; // I thought I wrote *p += 3
// ... Lots of other code in between, I forgot I accidentally changed p
*p += 3; // NOOOOOOOOOOO!
}
int main()
{
int z=8;
F(&z);
std::cout << z;
return 0;
}
I got a segmentation fault, because I'm writing at an address where I haven't allocated a variable (for all I know I could have just screwed up my boot sector).
Finally, about const after a function declaration: it makes the this pointer a const pointer - basically the compiler emits const A* this instead of just A* this. Conceptually, it states your intention that the function will not change the state of the class, which usually means it won't change any of the (internal) variables. For example, it would make the following code illegal:
class A {
int a;
void f() const {
a = 3; // f is const, so it cannot change a!
}
};
A a;
a.f();
Of course, if the function returns something, this value can have its own type, for example
void f();
int f();
int& f();
const int f();
const int& f();
are functions that return nothing, a (copy of) an integer, a (reference to) an integer, a constant (copy of) an integer, and a constant reference of an integer. If in addition f is guaranteed not to change any class fields, you can also add const after the brackets:
void f() const;
int f() const;
int& f() const;
const int f() const;
const int& f() const;
The way I remember the difference between references and pointers is that a reference must exist and the reference cannot change.
A pointer can be changed, and usually needs to be checked against NULL or tested to verify it points to a valid object.
Also, an object passed by reference can be treated syntactically like it was declared in the function. Pointers must use deferencing syntax.
Hope that helps.
You are confusing things.
First of all int z=8; F(&z); here z IS NOT a reference.
So let me start with the basics:
when found in a type declaration the symbol & denotes a reference, but in any other context, the symbol & means address of.
Similar, in a type declaration * has the meaning of declaring a pointer, anywhere else it it the dereferencing operator, denoting you use the value at an address.
For instance:
int *p : p is a pointer of type int.
x = *p : x is assigned the value found at address p.
int &r = a : r is reference of type int, and r refers the variable a.
p = &a : p is assigned the address of variable a.
Another question you have: the const at the end of a function, like int f(int x) const. This can be used only on non-static class methods and specifies that the function does not modify the object. It has nothing to do with the return value.

Pointer to reference assignment

I'm a bit confused about the assignment in C++:
Q1: Why this works:
int *z = &x;(1)
while this, of course, doesn't work:
*z = &x;(2)
Q2: Same kind of question for function:
funct(int *z)
And you call it:
int x;
func(&x);
does it mean *z=&x?
I know I passed the address in the above case (z=&x). But should the two terms on two sides of the assignment should be exactly the same?
Assuming x is declared as an int
int x;
Then your first line
int *z = &x;
Says declare z to be of type pointer to int. Initialize it with a pointer to the int x. All good. It type checks fine. z is a pointer to an int, and so is &x.
But now
*z = &x;
fails because z is a pointer to an int, so *z is an int! You can't assign &x, which is a pointer to an int, to an int. That is a type mismatch.
Now in your function call question
void func(int *z) {...}
Your call
func(&x);
is fine. It passes &x, a pointer to an int, by value to the parameter z, which is itself a pointer to an int. Inside of func you do get the effect of z = &x. Parameter passing by value is very much like assignment.
ADDENDUM
The reason you will see a value such as &x passed to a parameter declared with a pointer type such as int *z is that it allows the caller's x to be modified through the parameter z. In other words:
void func(int *z) {
*z = *z + 1;
}
if called like this
int main() {
int x = 10;
func(&x);
cout << x << '\n';
}
will output 11. Passing &x to z means both that z == &x and *z == x, or even stronger, that *z and x are now aliases of the exact same entity in memory! Any change made to *z affects x and vice versa; the two expressions refer to the same memory location.
In pictures:
+-------+ +-------+
z | | | | *z
| +---+----------------------------->| |
&x | | | | x
+-------+ +-------+
int *z = &x;(1)
delares z to be of type "int*" The "* is a part of the type, and is not part of a pointer dereference -- so you are assigning "z = &x" and NOT "*z=&x"
That should alos explain why 2 does not work -- the correct statement for (2) would be
z = &x;
It is bad rule to write
int *z;
better write
int* z;
this leads to such confusions.
Here z is variable and int* is a type, similar to float and int types. This type is called a pointer. It stores an address in memory where you variable (including pointers) can be stored.
In C++ you assign one value of a type to another. So here every there you assign z = &x. This works because &x gives you a pointer to x. That does mean an address in memory where your int x variable lays.
Also you should not confuse declaration of variable:
int* z;
int x;
float& f; // reference variable
and expression:
*z;
&f;
In upper case * and & are parts of declaration, are parts of type like "short" is a part of type "short int". In lower case they are parts of expressions - operators like "+" and "-". These are completely different things, though you use same symbols for them.
When you write, *z = &x;, you are de-referencing the pointer z, meaning that you are trying to assign the pointee (an int) to the address of x
To assign the pointer (and not the pointee), please write z = &x;
When you write type* z or type *z the type specifier takes precedence and the '*' is a modifier of the type. Thus both int* z and int *z mean "declare z, such that z is a pointer to type int".
int* z = &i; // pointer-to-int z = the address of i
int *z; // z is a pointer-to-int
z = &i; // pointer-to-int z = the address of i
int *z; // z is a pointer-to-int
*z = &i; // take the address of i and store it in integer who's address z contains

Does int * & has any real sense?

I'm looking few exercise from university about C++ and I found out this exercise:
#include <iostream>
using namespace std;
int& f(int*&);
int& f(int*& x) {
*x = 5;
return *x;
}
int main() {
int y = 1, x;
int* z = &y;
x= f(z);
cout << y << " " << x <<endl;
}
I was wondering: does <any type>*& has any real sense? Isn't f(int*& x) the same as f(int x)? Aren't you passing the pointer to the L-value of the variable?
f(int*& x) is not the same as f(int x). In the first case x is a reference to an integer pointer whereas in the second case x is just an integer.
Lets start from the basics:
When you write f(int &x) means that x is a reference to an integer and you can change the value of x in the function and the change will be reflected in the calling function.
Similarly, when you write f(int*& x), it means that x is reference to an integer pointer and when you change the address that x points to, the change will also be reflected in the calling function.
With int* &x you are passing the same pointer(by reference). Otherwise with only int* x you are passing a copy of the pointer and then you can't change the original one in the function. &x makes x an alias of the original parameter.
It's a reference to a pointer to an int. The function is then able to change the pointer if it wants to. In your example it doesn't make sense, but it obviously does have a use.
nope: *& here doesn't mean "dereference addressof". It means: "pass a pointer byref".
int& f(int*& x) {
*x = 5; // note: changes the pointee, not the pointer
return *x;
}
In this example, you don't gain anything by passing the pointer by reference, since you're not changing the pointer. Passing a pointer by reference is only needed when you intend to change the pointer:
void f(int*& x) {
x = new int(42); // note: changes the pointer
}
I think you are confusing sybols when they are used as operators or declarators.
If you use * when declaring variable, that means veriable is a pointer. When you use * as operator, that is dereference operator.
int *& name
simply means you are taking pointer to int by reference. **The * and & do not cancel each other out.**
If you had line of code like this:
var = *& var2;
then yes, it would be same as:
var = var2;