When I create a local variable num
inside the main()
function and pass this variable into the function dosmth(const int& num)
that expects a reference to a constant integer, the program works just fine:
#include <iostream>
using namespace std;
void dosmth(const int& num) { // Same address. Non-modifiable.
cout << &num << endl;
// num++; // Compiler error
}
int main() {
int num = 10; // Same adress. Modifiable.
dosmth(num);
num++; // No compiler error.
cout<<#
return 0;
}
The current ISO C++ (2020) standard states in Section 9.4.3 that:
...... A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows:
If the reference is an lvalue reference and the initializer expression is an lvalue (but is not a bit-field), and “cv1 T1” is reference-compatible with “cv2 T2”,
or has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, and can be converted to an lvalue of type “cv3 T3”, where “cv1 T1” is reference-compatible with “cv3 T3” (this conversion is selected by enumerating the applicable conversion functions (12.4.1.6) and choosing the best one through overload resolution (12.4)),
then the reference is bound to the initializer expression lvalue in the first case and to the lvalue result of the conversion in the second case (or, in either case, to the appropriate base class subobject of the object) .........
In other words, the reference is bound to the initializer expression lvalue - which is a const int
in this case. However, I cannot understand how a locally declared variable in the main
function (i.e. int
) can be shared by two functions (main
and dosmth
) and occupy the same virtual address at the same time, while its type is different in the scope of these two functions (one is read-only, the other is not). As far as I know, passing-by-reference creates an alias to the actual parameter, which is not a copy but actually points to the actual variable. If the reference is bound to a const int
according to the standard, it should now point to a const int
, but what it points is a variable, namely num
.
You declared a non-constant object
int num = 10; // Same adress. Modifiable.
So it may be changed.
num++; // No compiler error.
You passed the object to the function by constant reference. So within the function the object may not be changed.
From the C++20 Standard (9.2.9.2 The cv-qualifiers)
3 A pointer or reference to a cv-qualified type need not actually point or refer to a cv-qualified object, but it is treated as if it does; a const-qualified access path cannot be used to modify an object even if the object referenced is a non-const object and can be modified through some other access path.
For example you can write
int x = 10;
const int &crx = x;
int &rx = x;
and then
rx += 20;
But you may not write
crx += 20;