What Is a Reference Variable in C++

When is a reference variable appropriate and why? Can you explain the actual syntax and placement? [duplicate]

You're mixing up two completely separate things here. Three examples to show how the two things work, individually and then together...

  1. A function can take a parameter passed by value, and return a value.

    double foo (double y)
    {
    y = y + 200.0;
    return y;
    }

    void main(void)
    {
    double hubble = 50.0;
    double bubble = 100.0;

    hubble = foo(bubble);

    std::cout << "hubble=" << hubble << ", bubble=" << bubble << std::endl;
    }

    Note that because this is passed by value, even though foo() changes y, bubble does not change. hubble is set to the value returned by foo().

    Then you get

    hubble=300, bubble=100
  2. A function can take a parameter passed by reference, and modify that parameter.

    void foo (double& y)
    {
    y = y + 200.0;
    }

    void main(void)
    {
    double hubble = 50.0;
    double bubble = 100.0;

    foo(bubble);

    std::cout << "hubble=" << hubble << ", bubble=" << bubble << std::endl;
    }

    Then you get

    hubble=50, bubble=300

    Of course hubble hasn't changed. But because bubble was passed by reference, the change to y inside foo() changes bubble, because that change is happening on the actual variable passed and not on a copied value.

    Note that you do not have a "return" statement here. The function does not return anything - it simply modifies the variable which is passed to it.

  3. And of course you can use both together.

    double foo (double& y)
    {
    y = y + 200.0;
    return y + 400.0;
    }

    void main(void)
    {
    double hubble = 50.0;
    double bubble = 100.0;

    hubble = foo(bubble);

    std::cout << "hubble=" << hubble << ", bubble=" << bubble << std::endl;
    }

    Then you get

    hubble=700, bubble=300

    As before, changing y inside foo() changes bubble. But now the function is returning a value as well, which sets hubble.

Why would you choose to return a value, or to modify the value passed in, or to do both? That entirely depends on how you write your code.

I agree with you that you don't have to use a pass-by-reference here. Myself, I'd probably just return a value. But this is a learning exercise, and you've been told to do it that way, so you've got to. Suppose your pass-by-reference is the discount? So a function "void discount(double& value)" takes the value passed and multiplies it by 0.85. It's a bit artificial, but it would demonstrate the principle.

Difference between reference and regular variable in C++?

Is there any way to tell that xRef is a reference to an int, rather than just being a normal int?

You can use std::is_reference:

#include <iostream>
#include <type_traits>

int main ()
{
int i = 0;
int& ri = i;

if (std::is_reference <decltype (i)>::value)
std::cout << "i is a reference\n";

if (std::is_reference <decltype (ri)>::value)
std::cout << "ri is a reference\n";
}

Output: ri is a reference

So,

Is int& its own type?

Yes it is.

What is the difference between a variable and a reference in C++? [duplicate]

Here is a way to understand the difference:

  • Objects that can change state are also called "variables".
  • Pointers are objects (variable or not). They have a state.
  • References are "nicknames". They don't have a state, but expose the state of the refereed object (which is why you can't re-assign a reference, it's not an actual object).

Now, in some cases references might be implemented as pointers, but from the language point of view, references are just not pointers, they really are additional names for an object already existing.

As pointers are objects, and have a state, passing pointers to functions will copy that state, the pointer's state, not the pointee's state. However, references have no state, so if you pass a reference to a function, it's the refereed object that you pass (by copy).

By observation, the use of variables names and references is
exchangeable. Is that true?

"References are nickname" is the best way to understand references.

What is the difference between passing a variable name as parameter
and passing a reference? e.g.,

void func(int a); vs void func2(int& b);

The first implementation ask for a copy of the object passed. That is, internally func() can do anything to a, without changing the object that was passed to func() because internally func() made a copy of that object and manipulates the copy, not the original.

The second implementation ask for "a nickname for an object already existing". First, the object have to exist and if passed, a nickname for it will be created inside the function. That nickname, the reference b, is still a nickname for the original object. This mean that any manipulation done to b will affect the original object passed to func2().

  • func() signature says "I need this data but I will not modify the original object passed.".
  • func2() signature says "I need an object that I WILL certainly modify, pass it so that I can modify it".

Bonus stage:

At this point, if you don't know yet about const, that might be useful: in function signatures const is used with references to specify the arguments that are "read-only".

Let me clarify:

void func3( const int& b);

Here func3 says: "I need to access to an object, but really I will not make a copy of it. However I guarantee that I will not change that object".

So, why would we need that? Because some objects are expensive to copy. int is cheap to copy so most people will just pass it and func() and func3() are basically equivalent (depends on implementation but generally true).

If however we want to pass, says, a very big object, like a data buffer, we really don't want to copy it again and again just to apply some algorithms.
So we do want to pass it by reference. However, depending on the function, sometime you want to extract information and work with it, so you only need "read-only" access to the argument. In this case you use const Object&. However, if you need to apply the algorithm to the object passed, you need to be able to modify it, which you could call "write-access". In this case, you need to use a normal reference.
Asking for a copy basically mean that you want to manipulate an object that is the same state than the passed object, but is not the passed object.

To summarize:

  • func( T object ) : I want to have a copy of an object of type T;
  • func( T& object ) : I want to have "write-access" to an object of type T - assume that I will modify that object!;
  • func( const T& object ) or func( T const & object ) // which are the same : I want to read the state of an object, but I guarantee you that I will not modify it, I want "read-only" access.

Actually, the "read-only" guarantee could be violated using const_cast<> but that's a different story and it's only used in some very very very narrow cases.

Last thing you need to know is that if you have a member function, then you can do:

class K{
public:
void func() const; // see the const?
};

In this specific case, what you say is that inside the function, which is basically equivalent to:
void func( const K* this );

In this case you can see that this is a pointer but it's pointing to a const object. This mean that func() guarantee that the object it is member of (this) is never modified through this function (except some specific cases, see mutable keyword, another long story).

C++: variables vs references?

In general, a reference is a variable. A reference is not an object of its own however. A reference is an entity that refers to an existing object.

While the compiler will in many cases (but not necessarily always) use the same mechanism (i.e., the passing around of addresses) by which pointers are implemented to also implement a reference, at the language level, pointers and references are completely different things. They both essentially express an indirection. However, a pointer is its own object with its own address, it needs to explicitly be dereferenced and its value can be changed. A reference is not an object itself (it, e.g., does not have an address or size), it's an entity that refers to an existing object.

The statement

int ival = 1024;

is a declaration as well as a definition of an object of type int that is initialized to the value 1024. So yes, an int object is created and the name ival is introduced. From that point on, ival is an id-expression that denotes that particular int object.

The statement

int &refVal = ival;

is a declaration and definition of a reference that refers to the int object designated by the expression ival. From that point on, the name refVal is an id-expression that denotes that object. So yes, the names refVal and ival both designate the same int object.

Note that while both ival and refVal are variables, there is only one object created by the two declaration statements above, which is the int object defined by the declaration that introduced ival.

In general, the name ival itself will only require storage in the internal data structures (symbol tables) used by your compiler and linker during compilation. ival is just a name you use in your code to identify an object. The compiled machine code will simply access whatever object that identifier identified accordingly (e.g., through its address). There is no need to explicitly represent names during runtine of your program (except for dynamic linking and debugging information). You will most likely not find the string "ival" anywhere in your compiled (release) binary.

A reference variable's address and value C++

I know that a reference variables's address cannot be changed once
set,

References have nothing to do with addresses. Don't think of references as special pointers.

Unless you are talking about how a compiler might implement references. But this is a completely different level of abstraction. On a C++ programmer level, you are not looking at the language from the same point of view as a compiler writer; there is no such thing as a "reference variable's address". Objects have addresses, and a reference is just a different way to name an object.

Or, as I like to explain it to beginners, a reference is the object.

but when I run the command how is my reference's value change but
the address is the same?

In the following line:

int &ref = a;   //&ref is 0x28fee

You are declaring ref to be a reference to a. Using the explanation from above, ref is a. So when you then go on and write &ref afterwards (using the & character to invoke the address-of operator, rather than declaring a reference), what happens is equivalent to what happens when writing &a. It is therefore not surprising that the result is identical. It's one and the same object, so the address must be the same.

ref = b;        //value of ref = 5, address is still 0x28fee

This is the same as writing a = b;. It assigns the value of b to a, because ref is just another way to say a. No addresses are changed when values are assigned to ints.

Lastly, is it correct to assume that the "&" sign is same the one we
use in pointers?

No, not at all. Reiterating my point from above: & has different meanings in C++. You use it to declare references or to take addresses of objects. Actually, there are even more meanings, considering that & is also the bit-wise AND operator, as in a & b. Pairs of &, i.e. &&, extend the list of possible meanings to include the logical AND operator and C++11 rvalue references.


From a teaching point of view, it is of course unfortunate that & is overloaded for reference declarations and the address-of operator. As far as I know, & was chosen for references because back then, it was difficult to add new keywords (like ref) to C++ as backward compatibility with C was a huge concern at that time, and adding ref as a keyword would have meant that C code like int ref = 0; would no longer compile.

C++ had to introduce at least some new keywords (e.g. throw), but in certain cases it was technically possible and/or politically necessary to do without them.

Passing by reference in C

Because you're passing the value of the pointer to the method and then dereferencing it to get the integer that is pointed to.



Related Topics



Leave a reply



Submit