1

I am experimenting with C++ references and came across the following scenario : Consider the following code

void foo(float &y)
{
    float k = 0.0;
    k += 20.1;
    y = k;
    cout << "y = " << y << endl;
} 



int main() {

    float  i;
    foo(i);
    i+=10.00;
    cout<<"value of I after returning is :: "<<i<<endl;

    return 0;
}

The program compiles and runs. The output is :

y = 20.1
value of i after returning is :: 30.1

Now with that happening my dilemma is that ... in function "foo" we assign y (which is a reference to i) as k. And k's scope is only in that function. So once the function returns, k should be destroyed and the value of i should be some undefined value. But contrary to my expectation, i has the value of k after the function.

Am I missing something or understanding things differently ... ? Any help in understanding what is happening here ? Thanks in advance.

AdityaG
  • 428
  • 1
  • 3
  • 17
  • try foo(float* y) and in the main foo(&i) – Engine Jul 10 '15 at 08:16
  • _"So once the function returns, k should be destroyed and the value of i should be some undefined value."_ _`y = k;`_ It will be copied, no need to worry. – πάντα ῥεῖ Jul 10 '15 at 08:16
  • I'm 100% sure that this has been covered before: A reference can only be "set" to its referand once - in this case at the call to `foo`. The `y=k` only sets the VALUE of `i` in `main` to the value of `k` in `foo`. – Mats Petersson Jul 10 '15 at 08:17
  • you have assigned a new value to y and reference doesn't come into picture here. – The Apache Jul 10 '15 at 08:31
  • [Different question](http://stackoverflow.com/questions/27792604/why-it-is-illegal-to-copy-an-object-if-a-member-of-the-class-is-a-reference/27792636) with similar answer – Mohit Jain Jul 10 '15 at 13:37

3 Answers3

2

I think you are confusing C++ references with pointers. They are different things! Once a reference is set to reference some object, it can never be changed to refer to another object. And any operation that is performed on the reference is actually done to the value of the referred object. In this case, the assignment y = k actually sets the value of the object referred to by y to k.

To make things a bit more concrete, I will annotate the example you gave with comments describing what is happening:

void foo(float &y)
{
    float k = 0.0;
    k += 20.1;
    y = k;  /* The value of the object referred to by y (i, in this program)
               is set to k (20.1f) */
    cout << "y = " << y << endl; /* When we write y in this way, we are 
               really referring to the value of the object referred to by y. 
               This is why it prints 20.1 instead of some memory address. */
} 

int main() {
    float  i;
    foo(i);   /* i is passed as a reference to foo */
    i+=10.00; /* The value of i was modified in foo. */
    cout<<"value of I after returning is :: "<<i<<endl;

    return 0;
}

To contrast, here is similar code using pointers instead of references (with a mistake-- it assigns the pointer, y, instead of changing the value pointed at by y):

void foo(float *y)
{
    float k = 0.0;
    k += 20.1;
    y = &k;
    cout << "y = " << *y << endl;
} 

int main() {
    float  i = 0;
    foo(&i);   /* i is passed as a reference to foo */
    i+=10.00; /* The value of i was modified in foo. */
    cout<<"value of I after returning is :: "<<i<<endl;

    return 0;
}

What happens in this case? Well, we print out y = 20.1 and that the value of i after returning is 10.00. In this example, when we assign y = &k we are changing the variable y, which is local to foo, to refer to k. This has no effect on i (we are not modifying the value pointed to by y), so i is unchanged after we exit foo. If you wanted to change i to equal k after foo, we would have to change the line to read *y = k.

Hope that cleared up some of the differences between C++ references and pointers! There are plenty of good tutorials out there that do an excellent job explaining the topic.

Duke
  • 339
  • 1
  • 1
1
float &y = k;  // Or float &y argument of a function initialized with i

is very different from

float &y = something;
...
y = k;

In former version, y is a reference of k.

In later version, y is still reference of something, and y = k, assigns value to k to y alias or something

Always remember that a reference can not be re-assigned.

for example:

int x = 10;
int &y = x;
int z = 20;

y = z;  // x= 20, y(x) = 20, z = 20
x = 15; // x= 15, y(x) = 15, z = 20
y= 25;  // x= 25, y(x) = 25, z = 20
z= 30;  // x= 25, y(x) = 25, z = 30
// Also note that &x and &y (addresses) are same. But &z would be different
Mohit Jain
  • 30,259
  • 8
  • 73
  • 100
0

References are syntactic sugar for pointers. Your code is equivalent to the following:

void foo(float * const y)
{
    float k = 0.0;
    k += 20.1;
    *y = k;
    cout << "y = " << *y << endl;
} 
int main() {
    float  i;
    foo(&i);
    i+=10.00;
    cout<<"value of I after returning is :: "<<i<<endl;
    return 0;
}

Basically, you can set the target of the reference only at initialisation. If you assign to the reference afterwards, then these will be assignments to the referenced value.

Daniel Jour
  • 15,896
  • 2
  • 36
  • 63
  • 2
    Would you prefer `float *const y` instead of `float *y`? Moreover reference is [not just](http://stackoverflow.com/questions/31262942/c-references-are-they-just-syntactic-sugar) syntactic sugar and provide stronger guarantees? – Mohit Jain Jul 10 '15 at 08:29
  • `void foo(float *y)` is not the same as `void foo(float& y)`, one is a pointer to a float, one is a reference to a float .. I can pass nulls to one, I cannot to the other – txtechhelp Jul 10 '15 at 08:31
  • @MohitJain Indeed, changed. I was looking for the exact wording in the standard, but couldn't find it. Thanks for the link. – Daniel Jour Jul 10 '15 at 08:34
  • Cannot find it in the latest draft, I'm sure I once read something about this in a standard ("syntactic variant" or something like that), perhaps in an older version. – Daniel Jour Jul 10 '15 at 08:51