Returning a reference

Started by
14 comments, last by DevFred 14 years, 10 months ago
I always thought that you are required to give a function the exact same type that it specifies in its definition. Here is a snippit of code that I was looking at that assigns a vector to a function that asks for a reference.
[source lang=cpp]
string& foo(vector<string>& inventory, int i); 

int main()
{
    vector<string> inventory;
    cout << foo(inventory, 0) << "\n\n";
}


The "vector<string>&" appears to call for a reference to a vector of strings. Inventory is only defined as a vector of strings here: "vector<string> inventory." How can we use inventory as a value for the function inventory, since it isn't a reference? Does this statement say that vector<string>& inventory = vector<string> inventory, that is, does make declare and define a reference?
Advertisement
Consider this:
vector<string> inventory;vector<string>& referenceToInventory = inventory;//!!!referenceToInventory.resize(10);if( inventory.size() == 10 )  cout << "yay references work";


On the line commented as "!!!", a reference is created that "aliases" a value.

This is what is happening when you call that function. It wants a reference, you give it a value, so it's reference variable is assigned to/aliases your value.
When you see a reference in a function argument list, think 'pass-by-reference' rather than 'pass a reference.' The two phrases say exactly the same thing, but the first one does a better job of conveying what's really going on: 'the vector is being passed by reference to the function' as opposed to 'the function is receiving a reference to an existing vector.' Both are true, but the former is a more helpful way to think about it.

As for why it works: consider it hand-waving on the part of your compiler. When it sees a function with a pass-by-reference argument, and it sees the function used with syntax for pass-by-value, it waves its little digital fingers and reference-izes the thing for you. This can be a blessing and a curse; on the one hand, you don't have to worry about it. On the other... you probably won't worry about it. Make sure you keep track of when variables are being passed by-reference and by-value, and try to use pass-by-reference-to-const as much as possible.
Quote:Original post by Hodgman
Consider this:
*** Source Snippet Removed ***

On the line commented as "!!!", a reference is created that "aliases" a value.

This is what is happening when you call that function. It wants a reference, you give it a value, so it's reference variable is assigned to/aliases your value.


awesome. Just as I thought. Now what if i were to give the function a reference to inventory to begin with? Would the function make a reference to my reference? or would it simply use it as opposed to creating a new one?

the former sounds sort of inefficient and pointless, but you never know?

Also, does the same process apply for pointers? If I pass a value to a function that asks for a pointer, will it have a pointer point to my value?
Its an optimization. You just call the function with your value. That requires the function to copy the value on the stack. You can think for yourself what that means if you have quite a huge vector. So the optimization is that the function declares its parameter as reference. You still hand it the value but it does not copy the value but uses roughly spoken the memory address of your value to access the data without copying it. You value "gets referenced" by the compiler automatically so you do not need to create a reference yourself.
------------------------------------I always enjoy being rated up by you ...
Quote:Original post by zoner7
Would the function make a reference to my reference? or would it simply use it as opposed to creating a new one?

If you hand in the correct type (a reference in this case) it will use it because there is no need to "reinterpret" the incoming parameter to make its type fit.

Quote:Original post by zoner7
Also, does the same process apply for pointers? If I pass a value to a function that asks for a pointer, will it have a pointer point to my value?

Same goes here. If the function asks for a pointer and you give it a pointer the function takes it as pointer. But if you try to hand in a value the compiler won't accept that. In can reference values but it is not allowed to make a pointer from a value:

void foo(int *);int i = 0;foo(i);  // <- wont even compilefoo(&i); // <- is the way to go here, note that now foo can change actual value of i


Note that in this case the & means that you access the address of i as opposed to int &b = i; which would be a reference to i and not a pointer. To create you even more headache you can also create references to pointers [grin] ...
------------------------------------I always enjoy being rated up by you ...
Quote:Original post by zoner7
awesome. Just as I thought. Now what if i were to give the function a reference to inventory to begin with? Would the function make a reference to my reference? or would it simply use it as opposed to creating a new one?

the former sounds sort of inefficient and pointless, but you never know?

Also, does the same process apply for pointers? If I pass a value to a function that asks for a pointer, will it have a pointer point to my value?


I'm pretty sure that references-to-references are actually forbidden by the C++ standard. I might be crazy, but I think I read that somewhere. So, in answer to your first question: the function would just get a reference to your value, as normal.

As for pointers, think of them just like any other value-type. When you pass a pointer, the pointer is passed by value. Since passing by value creates a copy, the new (copied, function-scope) pointer will point to the same address as the original.


Quote:Original post by zoner7
Also, does the same process apply for pointers? If I pass a value to a function that asks for a pointer, will it have a pointer point to my value?

Same goes here. If the function asks for a pointer and you give it a pointer the function takes it as pointer.

I meant to say what happens when I don't pass the function a pointer. I pass it a value instead of a pointer, even though it calls for a pointer. Will the function make a pointer to my value, just as it does with references in the previous scenario, or will I get a compile error?
Yeah sorry, I was reading to fast. I have edited my post above, this wont compile at all.
------------------------------------I always enjoy being rated up by you ...
Quote:Original post by Ariste
Quote:Original post by zoner7
awesome. Just as I thought. Now what if i were to give the function a reference to inventory to begin with? Would the function make a reference to my reference? or would it simply use it as opposed to creating a new one?

the former sounds sort of inefficient and pointless, but you never know?

Also, does the same process apply for pointers? If I pass a value to a function that asks for a pointer, will it have a pointer point to my value?


I'm pretty sure that references-to-references are actually forbidden by the C++ standard. I might be crazy, but I think I read that somewhere. So, in answer to your first question: the function would just get a reference to your value, as normal.

As for pointers, think of them just like any other value-type. When you pass a pointer, the pointer is passed by value. Since passing by value creates a copy, the new (copied, function-scope) pointer will point to the same address as the original.


Would that imply that it is more efficient to pass by reference? If I actually give a function a reference, it does not need to make an extra variable. But if I pass any variable, whether it be a pointer or a value, to a function that calls for a pointer, it is still considered as passing by value and will still create a new pointer.

This topic is closed to new replies.

Advertisement