Does dereferencing a pointer and passing that to a function which takes its argument by reference create a copy of the object?
In this case the value at the pointer is copied (though this is not necessarily the case as the optimiser may optimise it out).
int val = *pPtr;
In this case however no copy will take place:
int& rVal = *pPtr;
The reason no copy takes place is because a reference is not a machine code level construct. It is a higher level construct and thus is something the compiler uses internally rather than generating specific code for it.
The same, obviously, goes for function parameters.
In the simple case, no. There are more complicated cases, though:
void foo(float const& arg);
int * p = new int(7);
foo(*p);
Here, a temporary object is created, because the type of the dereferenced pointer (int) does not match the base type of the function parameter (float). A conversion sequence exists, and the converted temporary can be bound to arg since that's a const reference.
Hopefully it does not : it would if the called function takes its argument by value.
Furthermore, that's the expected behavior of a reference :
void inc(int &i) { ++i; }
int main()
{
int i = 0;
int *j = &i;
inc(*j);
std::cout << i << std::endl;
}
This code is expected to print 1 because inc takes its argument by reference. Had a copy been made upon inc call, the code would print 0.
No. A reference is more or less just like a pointer with different notation and the restriction that there is no null reference. But like a pointer it contains just the address of an object.
Related
Why these definitions are all ok:
int func(int p=255) {
return p;
}
int func1(const int &p=255) {
return p;
}
but this definition:
int func2(int &p=255) {
return p;
}
leads to compile error ?
What is the logic behind it ?
Taking arguments by reference means, you dont work with your local copy of the variable, but with a variable already defined in the scope of the calling function.
While your first example makes sense (you have a local variable p that you can fill with a default value) the second example is a bit more tricky: Usually when using references you expect the variable to have an address, since you want to modify it. For const-refernces, the compiler will still allow you to pass a literal, even if something like "reference to a literal" makes no sense at all.
In the third case the compiler expects you to modify p. But what part of the memory should this modification affect? "255" has no address - therefore it cant be used as a reference.
If you want to have a more detailed explanation, you should probably look for keywords like "rvalue" and "lvalue".
The attempted function definition
auto func2( int& p = 255 )
-> int
{ return p; }
… fails because you can't bind an rvalue to a reference to non-const. Basically that rule is because a simple value like 255 isn't modifiable. While the reference can be used to modify.
One simple solution is to express the default as a separate overload:
auto func2( int& p )
-> int
{ return p; }
auto func2()
-> int
{
int scratchpad = 255;
return func2( scratchpad );
}
A non-const reference must be bound to lvalue (i.e. its address could be got). 255 (i.e. an int literal) is not a lvalue, so int &p=255 fails.
A const reference could be bound to rvalue, and for this case, a temporary int will be created and initialized from 255. The temporary int's lifetime will be the same as the const reference.
int func(int p=255) {
return p;
}
p here is copied by value, and it is defined to exist in the scope of func.
int func2(int &p) {
return p;
}
// e.g. use:
int value = 10;
func2(value); // func2 *could* modify value because it is passed by non-const reference
In this case the compiler here expects p to have a name somewhere in memory (i.e. lvalue), so it can possibly write to it within func2. Passing by non-const reference allows you to modify the variable used in the function call. Since p must belong to someone else somewhere since it can be modified, you can't assign a default value to it.
But what about the const-reference case? Here, the compiler is smart enough to know that p can never be written to since it is const, so it doesn't need to have a name in memory to write to. In cases of a literal being passed (e.g. 255), it (behind the scenes) essentially creates a temporary and passes that temporary variable to the function.
int func1(const int &p=255) {
return p;
}
func1(10);
// Behind the scenes, the compiler creates something along these lines
// since it can never be modified.
const int some_temporary = 10;
func1(some_temporary);
I'm learning C and I'm still not sure if I understood the difference between & and * yet.
Allow me to try to explain it:
int a; // Declares a variable
int *b; // Declares a pointer
int &c; // Not possible
a = 10;
b = &a; // b gets the address of a
*b = 20; // a now has the value 20
I got these, but then it becomes confusing.
void funct(int a) // A declaration of a function, a is declared
void funct(int *a) // a is declared as a pointer
void funct(int &a) // a now receives only pointers (address)
funct(a) // Creates a copy of a
funct(*a) // Uses a pointer, can create a pointer of a pointer in some cases
funct(&a) // Sends an address of a pointer
So, both funct(*a) and funct(&a) are correct, right? What's the difference?
* and & as type modifiers
int i declares an int.
int* p declares a pointer to an int.
int& r = i declares a reference to an int, and initializes it to refer to i.
C++ only. Note that references must be assigned at initialization, therefore int& r; is not possible.
Similarly:
void foo(int i) declares a function taking an int (by value, i.e. as a copy).
void foo(int* p) declares a function taking a pointer to an int.
void foo(int& r) declares a function taking an int by reference. (C++ only)
* and & as operators
foo(i) calls foo(int). The parameter is passed as a copy.
foo(*p) dereferences the int pointer p and calls foo(int) with the int pointed to by p.
foo(&i) takes the address of the int i and calls foo(int*) with that address.
(tl;dr) So in conclusion, depending on the context:
* can be either the dereference operator or part of the pointer declaration syntax.
& can be either the address-of operator or (in C++) part of the reference declaration syntax.
Note that * may also be the multiplication operator, and & may also be the bitwise AND operator.
funct(int a)
Creates a copy of a
funct(int* a)
Takes a pointer to an int as input. But makes a copy of the pointer.
funct(int& a)
Takes an int, but by reference. a is now the exact same int that was given. Not a copy. Not a pointer.
void funct(int &a) declares a function that takes a reference. A reference is conceptually a pointer in that the function can modify the variable that's passed in, but is syntactically used like a value (so you don't have to de-reference it all the time to use it).
Originally in C there were pointers and no references. Very often though we just want to access a value without copying it and the fact that we're passing around an address and not the actual value is an unimportant detail.
C++ introduced references to abstract away the plumbing of pointers. If you want to "show" a value to a function in C++ then references are preferable. The function is guaranteed that a reference is not null and can access it as if it were the value itself. Pointers are still necessary for other purposes, for example, you can "re-aim" a pointer or delete with a pointer but you can't do so with a reference.
Their functionality does overlap and without a bit of history it should confuse you that we have both.
So the answer to your direct question is that very often there is no difference. That said, f(int*) can be useful if you want the function to be able to check if the pointer is null. If you're using C then pointers are the only option.
The meaning of * is dependent on context. When in a data or function argument declaration, it is a datatype qualifier, not an operator int* is a datatype in itself. For this reason it is useful perhaps to write:
int* x ;
rather than:
int *x ;
They are identical, but the first form emphasises that it the * is part of the type name, and visually distinguishes it from usage as dereference operator.
When applied to an instantiated pointer variable, it is the dereference operator, and yields the the value pointed to.
& in C is only an operator, it yields the address (or pointer to) of an object. It cannot be used in a declaration. In C++ it is a type qualifier for a reference which is similar to a pointer but has more restrictive behaviour and is therefore often safer.
Your suggestion in the comment here:
funct(&a) // Sends an address of a pointer
is not correct. The address of a is passed; that would only be "address of a pointer" is a itself is a pointer. A pointer is an address. The type of an address of a pointer to int would be int** (a pointer to a pointer).
Perhaps it is necessary to explain the fundamentals of pointer and value variables? A pointer describes the location in memory of a variable, while a value describes the content of a memory location.
<typename>* is a pointer-to-<typename> data type.
&*<value-variable> yields the address or location of <variable> (i.e. a pointer to <variable>),
**<pointer-variable> dereferences a pointer to yield the the value at the address represented by the pointer.
So given for example:
int a = 10 ;
int* pa = &a ;
then
*pa == 10
When you do func(&a) that's called a "call by reference" that means your parameter "a" can actually be modified within the function and any changes made will be visible to the calling program.
This is a useful way if you want to return multiple values from a function for example:
int twoValues(int &x)
{
int y = x * 2;
x = x + 10;
return y;
}
now if you call this function from your main program like this:
int A, B;
B = 5;
A = twoValues(B);
This will result in:
A holding the value 10 (which is 5 * 2)
and B will hold the value 15 (which is 5 + 10).
If you didn't have the & sign in the function signature, any changes you make to the parameter passed to the function "twoValues" would only be visible inside that function but as far as the calling program (e.g. main) is concerned, they will be the same.
Now calling a function with a pointer parameter is most useful when you want to pass an array of values or a list. Example:
float average ( int *list, int size_of_list)
{
float sum = 0;
for(int i = 0; i < size_of_list; i++)
{
sum += list[i];
}
return (sum/size_of_list);
}
note that the size_of_list parameter is simply the number of elements in the array you are passing (not size in bytes).
I hope this helps.
C++ is different from c in many aspects and references is a part of it.
In terms of c++ context:
void funct(int *a) // a is declared as a pointer
This corelates to the use of pointers in c..so, you can compare this feature to that of c.
void funct(int &a) // a now receives only pointers (address)
This would lead to the reference usage in c++...
you cannot corelate this to that of c..
Here is a good q&a clarifying differences between these two.
What are the differences between a pointer variable and a reference variable in C++?
#include<iostream>
using namespace std;
int &fun()
{
static int x = 10;
return x;
}
int main()
{
fun() = 30;
cout << fun();
return 0;
}
Function fun() is returning value by reference but in main() method I am assigning some int to function. Ideally, a compiler should show an error like lvalue required but in above case the program works fine. Why is it so?
It's loose and sloppy language to say "a function returns something". It's OK as a shorthand if you know how to work with that, but in this case you get confused.
The more correct way to think about it is that you evaluate a function call expression. Doing that gives you a value. A value is either an rvalue or an lvalue (modulo details).
When T is an object type and you evaluate a function that has return type T, you get a value of type T which is an rvalue. On the other hand, if the function has return type T &, you get a value of type T which is an lvalue (and the value is the thing bound to the reference in the return statement).
Returning a reference is quite useful.
For example it's what std::map::operator[] does. And I hope you like the possibility of writing my_map[key] = new_value;.
If a regular (non-operator) function returns a reference then it's ok to assign to it and I don't see any reason for which this should be forbidden.
You can prevent assignment by returning a const X& or by returning X instead if you really want.
You can rewrite the code using pointers, which might be easier to understand:
#include<iostream>
using namespace std;
int *fun() //fun defined to return pointer to int
{
static int x = 10;
return &x; // returning address of static int
}
int main()
{
*fun() = 30; //execute fun(), take its return value and dereference it,
//yielding an lvalue, which you can assign to.
cout << *fun(); //you also need to dereference here
return 0;
}
References can be very confusing from a syntax point of view, as the dereferencing of the underlying "pointer" is implicitly done by the compiler for you. The pointer version looks more complicated, but is clearer or more explicit in its notation.
PS: Before someone objects to me regarding references as being a kind of pointer, the disassembly for both code versions is 100% identical.
PPS: Of course this method is a quite insidious breach of encapsulation. As others have pointed out, there are uses for this technique, but you should never do something like that without a very strong reason for it.
It works becuse the result of that function is an lvalue. References are lvalues. Basically, in the whole point of returning a non-const reference from a function is to be able to assign to it (or perform other modifications of referenced object).
In addition to other answers, consider the following code:
SomeClass& func() { ... }
func().memberFunctionOfSomeClass(value);
This is a perfectly natural thing to do, and I'd be very surprised if you expected the compiler to give you an error on this.
Now, when you write some_obj = value; what really happens behind the scenes is that you call some_obj.operator =(value);. And operator =() is just another member function of your class, no different than memberFunctionOfSomeClass().
All in all, it boils down to:
func() = value;
// equivalent to
func().operator =(value);
// equivalent to
func().memberFunctionOfSomeClass(value);
Of course this is oversimplified, and this notation doesn't apply to builtin types like int (but the same mechanisms are used).
Hopefully this will help you understand better what others have already explained in terms of lvalue.
I was buffled by similar code too - at fist. It was "why the hell I assign value to a function call, and why compiler is happy with it?" I questioned myself. But when you look at what happens "behind", it does make sense.
As cpp and others poined out, lvalues are "memory locations" that have address and we can assign values to them. You can find more on the topic of lvalues and rvalues on the internet.
When we look at the function:
int& fun()
{
static int x = 10;
return x;
}
I moved the & to the type, so it's more obvious we are returning a reference to int.
We see we have x, which is lvalue - it has address and we can assign to it. It's also static, which makes it special - if it wasn't static, the lifetime (scope) of the variable would end with stack unwinding upon leaving the function and then the reference could point to whatever black hole exists in the universe. However as x is static, it will exist even after we leave the function (and when we come back to the function again) and we can access it outside of the function.
We are returning reference to an int, and since we return x, it's reference to the x. We can then use the reference to alter the x outside of the function. So:
int main()
{
fun();
We just call the function. Variable x (in scope of fun function) is created, it has value of 10 assigned. It's address and value exist even after function is left - but we can't use it's value, since we don't have it's address.
fun() = 30;
We call the function and then change the value of x. The x value is changed via the reference returned by the function. NOTE: the function is called first and only after the function call was completed, then, the assignment happens.
int& reference_to_x = fun(); // note the &
Now we (finally) keep the reference to x returned by the function. Now we can change x without calling the function first. (reference_to_x will probably have the same address as the x have inside the fun function)
int copy_of_x = fun(); // no & this time
This time we create new int and we just copy the value of x (via the reference). This new int has its own address, it doesn't point to the x like reference_to_x is.
reference_to_x = 5;
We assigned x the value 5 through the reference, and we didn't even called the function. The copy_of_x is not changed.
copy_of_x = 15;
We changed the new int to value 15. The x is not changed, since copy_of_x have its own address.
}
As 6502 and others pointed out, we use similar approach with returning references a lot with containers and custom overrides.
std::map<std::string, std::string> map = {};
map["hello"] = "Ahoj";
// is equal to
map.operator[]("hello") = "Ahoj"; // returns reference to std::string
// could be done also this way
std::string& reference_to_string_in_map = map.operator[]("hello");
reference_to_string_in_map = "Ahoj";
The map function we use could have declaration like this:
std::string& map::operator[]( const std::string& key ); // returns reference
We don't have address to the string we "stored" in the map, so we call this overridden function of map, passing it key so map knows which string we would like to access, and it returns us reference to that string, which we can use to change the value. NOTE: again the function is called first and only after it was completed (map found the correct string and returned reference to it) the assignment happens. It's like with fun() = 10, only more beatiful...
Hope this helps anyone who still woudn't understand everything even after reading other answers...
L-value is a locator-value. It means it has address. A reference clearly has an address. The lvalue required you can get if you return from fun() by value:
#include<iostream>
using namespace std;
int fun()
{
static int x = 10;
return x;
}
int main()
{
fun() = 30;
cout << fun();
return 0;
}
#include<iostream>
int & fun();
int main()
{
int p = fun();
std::cout << p;
return 0;
}
int & fun()
{
int a=10;
return a;
}
Why is this program not giving error at line no.6 as "invalid conversion from int* to int", as it happens in case we do like this?
int x = 9;
int a = &x;
int& is a type; it means "a reference to int."
&x is an expression; it means "take the address of x." The unary & operator is the address operator. It takes the address of its argument. If x is an int, then the type of &x is "a pointer to int" (that is, int*).
int& and int* are different types. References and pointers are the same in many respects; namely, they both refer to objects, but they are quite different in how they are used. For one thing, a reference implicitly refers to an object and no indirection is needed to get to the referenced object. Explicit indirection (using * or ->) is needed to get the object referenced by a pointer.
These two uses of the & are completely different. They aren't the only uses either: for example, there is also the binary & operator that performs the bitwise and operation.
Note also that your function fun is incorrect because you return a reference to a local variable. Once the function returns, a is destroyed and ceases to exist so you can never use the reference that is returned from the function. If you do use it, e.g. by assigning the result of fun() to p as you do, the behavior is undefined.
When returning a reference from a function you must be certain that the object to which the reference refers will exist after the function returns.
Why is this program not giving error at line no.5 as "invalid conversion from int* to int", as it happens in case we do like this?
That's because you are trying to return the variable by reference and not by address. However your code invokes Undefined Behaviour because returning a reference to a local variable and then using the result is UB.
Because in one case its a pointer and in the other a reference:
int a=&x means set a to the address of x - wrong
int &p=fun() means set p to a reference to an int - ok
Functions in C++ are not same as macros i.e. when you qrite int p = fun() it doesn't become int p = &a; (I guess that is what you are expecting from your question). What you are doing is returning a reference from the function f. You are no where taking address of any variable. BTW, the above code will invoke undfeined behavior as you are returning a reference to the local variable.
You're not returning an int *, you're retuning an int &. That is, you're returning a reference to an integer, not a pointer. That reference can decay into an int.
Those are two different things, although they both use the ampersand symbol. In your first example, you are returning a reference to an int, which is assignable to an int. In your second example, you are trying to assign the address of x (pointer) to an int, which is illegal.
In C++,
function() = 10;
Works if function returns a variable by reference, right?
Would someone please elaborate on this in detail?
Consider this piece of code first
int *function();
...
*function() = 10;
Looks similar, isn't it? In this example, function returns a pointer to int, and you can use it in the above way by applying a unary * operator to it.
Now, in this particular context you can think of references as "pointers in disguise". I.e. reference is a "pointer", except that you don't need to apply the * operator to it
int &function();
...
function() = 10;
In general, it is not a very good idea to equate references to pointers, but for this particular explanation it works very well.
Consider the following code, MyFunction returns a pointer to an int, and you set a value to the int.
int *i;
i = MyFunction();
*i = 10;
Are you with me so far?
Now shorten that to
*(MyFunction()) = 10;
It does exactly the same thing as the first code block.
You can look at a reference as just a pointer that's always dereferenced. So if my function returned a reference - not a pointer - to an int the frist code block would become
int &i;
i = MyFunction();
i = 10;
and the second would become
MyFunction() = 10;
You still with me?
With a little experiment, you can determine if this will work or not.
Considering this example:
class foo {
private:
int _val;
public:
foo() { _val = 0; }
int& get() { return _val; }
void print() { printf("val: %d\n", _val); }
};
int main(void) {
foo bar;
bar.print();
bar.get() = 10;
bar.print();
}
And it's output is:
val: 0
val: 10
So sure enough, it is possible to return a reference. Note that the variable being referenced may go out of scope, then your caller may get garbage results (just like dereferencing a pointer to an object that has gone out of scope). So this would be bad:
int& get() {
int myval = _val;
return myval;
}
The answer to this question has to do with rvalue semantics versus lvalue semantics. Every value in C++ is either an lvalue or an rvalue. Lvalues are values that are stored in an addressable memory location, which implies they are assignable (assuming they are non-const, of course.) An rvalue is basically anything else, e..g literal constants, or non-addressable temporary values.
So, a function which returns a non-const reference is an lvalue. However, a function which returns by value would be an rvalue expression, because it returns a non-addressable temporary value, and is therefore not assignable.
See the wikipedia entry for a more detailed explanation with examples given.
A question you did not ask.
But why would you want to do that?
Think of the std::vector (I am extending the principle to methods).
Here you have the method 'operator[]()' It retuns a reference to the internal member.
This then allows the following:
std::vector<int> x(20,1);
x[5] = 10;
// This is quivalent to:
x.operator[](5) = 10;
// So this is just a function (method) call:
x.function(5) = 10;
As others noted function can return reference to member variable, but word of caution: this function should not be a part of class interface. Once you provide a function that returns reference to internals of your class, you loose control over them.
If you have not yet read "Effective C++", do it.
Item 29 of the book says "Avoid returning "handles" to internal data" and explains in more details why this practice needs to be avoided.
A word of warning, when returning a reference: pay attention to the lifetime of whatever you're returning. This example is bad:
int &function()
{
int x;
// BAD CODE!
return x;
}
...
function() = 10;
x doesn't exist outside of function, and neither do any references to it. In order to return a reference from a function, the object being referred to has to last at least as long as the reference. In the above example, x would need to be declared static. Other possibilities would be making x a global variable, or making function a class member function and returning a reference to a class member variable, or allocating x on the heap and returning a reference to that (although that gets tricky with deallocation)