I began learning C++ this week, and currently I am reading about compound types and constant variables. Unlike in most cases, references to const support type conversion by creating a temporary variable. But if so, then what's the difference in behaviour between:
int i = 42;
double di = 42;
and
int i = 42;
const double &di = 42;
Don't we end up with two independent variables that can end up having different values if we try to change i? Is the only difference that in the example with the const reference, the reference cannot be changed? The thing that bugs me the most is that when the types of a non-const variable and a const ref match, the reference points to the same address in memory and changes along with the change in the original variable, whereas this does not happen for a non-typematching const ref to a non-const variable:
#include <iostream>
int main() {
int i = 42;
const int &ri = i;
const double &dri = i;
++i;
std::cout << " at " << &i << ", " << ri << " at "
<< &ri << ", " << dri << " at " << &dri << std::endl;
int j = i;
int jj = ri;
int djj = dri;
std::cout << j << " at " << &j << ", " << jj << " at "
<< &jj << ", " << djj << " at " << &dri << std::endl;
return 0;
}
Output:
43 at %Address1%, 43 at %Address1%, 42 at %Address2%
43 at %Address3%, 43 at %Address4%, 42 at %Address2%
This seems to me like a major difference in behavior that is easy to overlook from simply looking at the syntax, on top of the fact that such behavior seems counter-intuitive to the entire idea of references. Also, why does jj is allocated a separate space, but not djj, which references the same address as dri?
Let's say you have a function of the form:
And now, let's say you have a
floatsomewhere. And you want to pass that to this function viafoo(f);. If aT const&could not bind to any object convertible toT, then this wouldn't work. Every user of this function that don't have adoublewould have to dofoo(static_cast<double>(f))or an equivalent.You might say that maybe
fooshould takedoubleby value. And fordoublespecifically, maybe it should.But what about if it's
std::string, and I want to callfoo("some string"). Well,"some string"is not astd::string; it is a string literal which is convertible tostd::string. So we allow that conversion.Again, you might say that it should take the
stringby value. But what about the cases when the caller really does have astd::string? They'd have to copy that string, a copy that is discarded and is therefore unnecessary.Of course, C++'s rules should be uniform. So if we want this to work for function arguments¶meters, it also has to work for named variables. But even then, it could be useful. You might call a function that you expect to return a string of some form, but aren't especially picky about which form. Just so long as it is convertible to a
std::string. This might be in template code:Do you really care if
get_a_stringreturnsstd::stringexactly, or just some string type convertible tostd::string? Probably the latter.