0

I am having trouble understanding when to use & with a variable. I think it changes the scope to that function but for some reason this code isn't working

void advanceTimeInMinutes(int& hours, int& minutes, int& advances)
{
    if(advances >=60-minutes){
        hours++;
        minutes=60-minutes+advances;
    }else{
        minutes +=advances;
    }
}

and it is called by

advanceTimeInMinutes( hour, minute, 50 );
phuclv
  • 37,963
  • 15
  • 156
  • 475
  • What does “isn’t working” mean? Do you get an error, or…? – Ry- Oct 11 '13 at 02:31
  • Yeah, it says "cannot convert parameter 3 from 'int' to 'int&' –  Oct 11 '13 at 02:32
  • 1
    `&` denotes a reference. You can’t pass a reference to a literal. Just declare it as `int advances`. – Ry- Oct 11 '13 at 02:33
  • @TheWaller A literal value is, well, literal. Like `5`, `1.23`, `'c'`, or `"foo"`. – Some programmer dude Oct 11 '13 at 02:35
  • 7
    If you don't know what literals, references, or pointers are you might want to read a good C++ book: [The Definitive C++ Book Guide and List](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) – Blastfurnace Oct 11 '13 at 02:39

3 Answers3

1

In many programming languages, the name you use to refer to the object is distinct from the object itself. One object may have several names.

The most direct way to assign multiple names to one object in C++ is to declare a name with the & specifier. (This usage is different from the & operator; a specifier is not an operator.)

When you declare those parameters with &, they become aliases of the object passed as an argument to the function. Such names are known as references.

C++ has several (alright, many) kinds and categories of expressions. Two important concepts are modifiability and ownership. When you pass a reference to a function, you optionally give it permission to modify the object, and ownership of the object. Modifiability is indicated by the absence of the const specifier, and ownership is indicated by use of && instead of & (this is new in C++11).

A function is not allowed to get modifiable, non-owning access to an object with only transient existence, since it should be able to expect to write results into such an object for return to the caller. The value 50 is stored in such a transient object.

One solution is to use int const & advances, but a better solution is not to use a reference at all, because you're not really trying to use an aliasing name to refer to a shared object.


Many make a conceptual assumption that a reference is an automatically-dereferenced const pointer. This works pretty well, and compilers pretty much always do things that way. But it's not necessarily true. For example, given this class definition:

struct s {
    static int x;
    int &r = x;
    char c;
};

The compiler could determine that r is always referencing a the global x, and replace every use of r with x. With no need to store a reference in every object, sizeof(s) could legally be 1.

This is more advanced than current C++ code analysis, but it will inevitably come at some point. Future-proof code shouldn't expect implementation of references to be equivalent to pointers.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • It's not "another name for the object", since the reference is a separate variable with its own distinct lifetime. It holds the address of the object, but unlike a pointer is dereferenced automatically, so you always access the referenced object and never the numeric value of the address. – Ben Voigt Oct 11 '13 at 03:41
  • 2
    @BenVoigt A reference is a name for its referent, no more and no less. There is no guarantee that any reference is backed by a pointer. – Potatoswatter Oct 11 '13 at 03:51
  • 1
    @BenVoigt No, I mean references are not objects. They have no storage. Any memory allocated in a struct to store a backing pointer is just optional padding. – Potatoswatter Oct 11 '13 at 04:09
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/39133/discussion-between-potatoswatter-and-ben-voigt) – Potatoswatter Oct 13 '13 at 01:27
0

& is a reference operator. It's used to change the value inside the function. The code above is equivalent to

void advanceTimeInMinutes(int *hours, int *minutes, int *advances)
{
    if(*advances >= 60 - *minutes){
        (*hours)++;
        *minutes = 60 - *minutes + *advances;
    }else{
        *minutes += *advances;
    }
}

advanceTimeInMinutes(&hour, &minute, &50);

As a number has no address, it'll cause an error

phuclv
  • 37,963
  • 15
  • 156
  • 475
-1

You can't pass a literal value as a reference. Since you never set the advance argument, then don't pass it by reference, so remove the & for that argument (and make it const as well (the fun thing is, if you make the argument const then you can use a reference)).

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    -1, this doesn't mention what a reference is or how anything relates to `&`, and the last sentence flatly contradicts the first, with no reconciliation between the two. – Potatoswatter Oct 11 '13 at 02:46