Reputation: 317
I have a very boring question.
I thought, when you do pass-by-reference for a C++ function, you literally have to pass a reference-type argument (or parameter?). But I saw in the resource that I am learning from, and all over the web basically, that I was wrong.
So, what is the real difference between these two and why both of them work?
scenario_1
#include <iostream>
int sum(const int& a, const int& b)
{
return (a + b);
}
int main()
{
const int a1 {2};
const int a2 {20};
std::cout << sum(a1, a2) << "\n";
}
scenario_2
#include <iostream>
int sum(const int& a, const int& b)
{
return (a + b);
}
int main()
{
const int& a1 {2};
const int& a2 {20};
std::cout << sum(a1, a2) << "\n";
}
Upvotes: 1
Views: 1223
Reputation: 118425
C++ has a lengthy, and occasionally confusing list of rules by which objects of one type are automatically converted to objects of some other, related type.
For example, you might have a function that takes a const char *
as a parameter, such as:
size_t strlen(const char *);
Despite that its parameter is a const char *
, you have excellent chances of success passing a non-const char
array to this function:
char buffer[256];
// Some code.
size_t l=strlen(buffer);
Your question regarding references is exactly the same thing. A modifiable lvalue is automatically convertable to a reference to a const object of the same type. You don't have to worry about it, the compiler will do it for you.
There are many other rules too. This might be your first introduction to C++'s automatic conversion rules (or implicit conversion rules). It won't be your last.
So, what is the real difference between these two and why both of them work?
There's no practical difference. There are some pedantic differences between the two versions, but they produce identical logical results.
Upvotes: 1
Reputation: 11230
A reference refers to an object instance somewhere else. When you use a reference to an object, all uses of that reference are as though you are using that original object. This allows one T&
to reference another T&
, etc -- but eventually it will have to reference an existing T
object from somewhere.
This answers the "why does it work" part of your question; because a reference simply refers to the instance itself.
The answer to your other question of "what is the real difference between these two" is a little more complicated. const
references in C++ are a little weird in that they are capable of extending the lifetime of temporary objects.
All objects in C++ have lifetime. Ordinarily, the lifetime of an object starts when they are created, and ends at the end of their scope -- whether this is just all part of an expression, or up to the literal ending }
scope. References view that lifetime, but don't normally affect the lifetime (which means that returning a reference to a temporary, for example will produce a dangling reference to an object that is no more).
const
references, on the other hand, extend the lifetime to the length of the enclosing scope. So when you have:
const int& a1 {2};
const int& a2 {20};
What you are actually doing is creating two temporary unnamed objects with values 2
and 20
, and the const int&
is extending the lifetime of these variables.
This is as if you did something like:
const int __unnamable_value_1 = 2;
const int __unnamable_value_2 = 20;
const int& a = __unnamable_value_1;
const int& b = __unnamable_value_2;
For the most part, I would recommend not thinking about this weirdness of C++. If you want to create a named value, create it by value (e.g. const T
). If you want to refer to an object possibly not constructed in the same place, use a reference (const T&
).
Upvotes: 1