What Is a Constant Reference? (Not a Reference to a Constant)

What is a constant reference? (not a reference to a constant)

The clearest answer.
Does “X& const x” make any sense?

No, it is nonsense

To find out what the above declaration means, read it right-to-left:
“x is a const reference to a X”. But that is redundant — references
are always const, in the sense that you can never reseat a reference
to make it refer to a different object. Never. With or without the
const.

In other words, “X& const x” is functionally equivalent to “X& x”.
Since you’re gaining nothing by adding the const after the &, you
shouldn’t add it: it will confuse people — the const will make some
people think that the X is const, as if you had said “const X& x”.

C++ Difference Between Const Reference to Non Const Object and Non Const Reference to Non Const Object

"What is the purpose for the "const" keyword for a reference if the object it is referencing is not a const object?"
The purpose is to prevent that reference being used to modify the object it is referencing.

int i = 42; // non const object
const int &r1 = i; // const reference to non const object
r1 = 6 * 9; // error, r1 cannot be used to modify i;

Difference between const reference and reference

Given the overload set:

void setage(int&a) { std::cout << "&"; }
void setage(const int&a) { std::cout << "&c"; }

the first function is called only with variables that are non-const:

int a = 42;
setage(a); // prints &

The second function is called if you pass it a variable that is const, or if you pass it a literal value:

int const b = 42;
setage(b); // prints c&
setage(42); // prints c&

Note that if this overload set is written within a class, the same rules apply, and which function is called still depends on whether the passed in argument is a literal, non-const variable, or const variable.

What is the difference between a const reference and normal parameter?

The difference is more prominent when you are passing a big struct/class:

struct MyData {
int a,b,c,d,e,f,g,h;
long array[1234];
};
void DoWork(MyData md);
void DoWork(const MyData& md);

When you use use 'normal' parameter, you pass the parameter by value and hence creating a copy of the parameter you pass. If you are using const reference, you pass it by reference and the original data is not copied.

In both cases, the original data cannot be modified from inside the function.


EDIT:

In certain cases, the original data might be able to get modified as pointed out by Charles Bailey in his answer.

Why no const reference in C++ just like const pointer?

References in C++ differ from pointers in several essential ways. One of the difference is:

Once a reference is created, it cannot be later made to reference another object; it cannot be reseated. This is often done with pointers.

It means Reference are like similar (see the link at the end of this answer) to const pointer (not pointer to a const!) in C++...

int a = 5;
int& m = a; // Behaves similar to int * const m = &a;
// See the link at the bottom for the differences between const pointer and reference.

and hence, you can't change/rebind them to point to some other address. So, you don't need a explicit const qualifier for a reference and that's why it is disallowed by the compiler.

See this link to learn Why are references not reseatable in C++?. I have copied the accepted answer of the above link:

The reason that C++ does not allow you to rebind references is given in Stroustrup's "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 a new reference value to r1 (re-binding r1) depending on the type of r2. I wanted to avoid such problems in C++.

EDIT:

See this link for Difference between const pointer and reference? (Thanks to @M.M for pointing out the ambiguity in my statement).

Why are references not const in C++?

This may seem counter-intuitive but I think the way to understand this is to realize that, in certain respects, references are treated syntactically like pointers.

This seems logical for a pointer:

int main()
{
boolalpha(cout);

int const i = 1;
cout << is_const<decltype(i)>::value << endl;

int const* ri = &i;
cout << is_const<decltype(ri)>::value << endl;
}

Output:

true
false

This is logical because we know it is not the pointer object that is const (it can be made to point elsewhere) it is the object that is being pointed to.

So we correctly see the constness of the pointer itself returned as false.

If we want to make the pointer itself const we have to say:

int main()
{
boolalpha(cout);

int const i = 1;
cout << is_const<decltype(i)>::value << endl;

int const* const ri = &i;
cout << is_const<decltype(ri)>::value << endl;
}

Output:

true
true

And so I think we see a syntactic analogy with the reference.

However references are semantically different to pointers especially in one crucial respect, we are not allowed to rebind a reference to another object once bound.

So even though references share the same syntax as pointers the rules are different and so the language prevents us from declaring the reference itself const like this:

int main()
{
boolalpha(cout);

int const i = 1;
cout << is_const<decltype(i)>::value << endl;

int const& const ri = i; // COMPILE TIME ERROR!
cout << is_const<decltype(ri)>::value << endl;
}

I assume we are not allowed to do this because it doesn't appear to be needed when the language rules prevent the reference from being rebound in the same way a pointer could(if it is not declared const).

So to answer the question:

Q) Why “reference” is not a “const” in C++?

In your example the syntax makes the thing being referred to const the same way it would if you were declaring a pointer.

Rightly or wrongly we are not allowed to make the reference itself const but if we were it would look like this:

int const& const ri = i; // not allowed

Q) we know once a reference is bind to a name/variable, we cannot change this binding, we change its binded object.
So I suppose the type of ri should be same as i: when i is a int const, why ri is not const?

Why is the decltype() not transferred to the object the referece is bound to?

I suppose this is for semantic equivalence with pointers and maybe also the function of decltype() (declared type) is to look back at what was declared before the binding took place.

How do constant references work?

I have also learned that passing a constant reference prevents the original object from being modified [...]

Not quite. You are not allowed to modify the object through the const &. In other words, you have read-only access. But nothing natively prevents other code with read-write access (for example the original owner of the referred object) to modify it. You do need to be careful when designing so that such changes do not surprise you.

A const & refers to a nonvolatile variable. The variable changes. Does the change invalidate the const &?

In C++, can the value of a const & change?

Yes, but not through that reference (ignoring mutable fields).

void foo(const int& c, int& mut) {
std::cout << c << " ";
++mut; // changes `c` if &c == &mut
std::cout << c << std::endl;
}

and

int a = 42;
foo(a, a); // 42 43

does anything prevent an optimizing compiler from merging old_r and new_r into a single constant object, treating the line as though it read as follows?

The as-if rule allows compiler to optimize if visible side effect are the same,

which is not the case here. So your "proposed merge of variable" in your code cannot be done fortunately.

C++: Variable that is passed by const referance changes value

Your code is rather complicated. Though much less is needed to see that the assumption: "A const reference does not change its value." is based on a misunderstanding.

#include <iostream>

struct foo {
const int& x;
};

int main()
{
int a = 42;
foo f{a};
a = 0;
std::cout << f.x;
}

The output of this is 0 even though f.x was initialized with a when a had the value 42. f holds a constant reference to a. This merely implies that you cannot modify a via f.x. It does not imply that x cannot be modified through other means. A constant reference is not a reference to a constant!



Related Topics



Leave a reply



Submit