tags:

views:

130

answers:

3

I've been playing around with references (I'm still having issues in this regard).

1- I would like to know if this is an acceptable code:

int & foo(int &y)
{
    return y;  // is this wrong?
}

int main()
{
    int x = 0;    
    cout << foo(x) << endl;

    foo(x) = 9;   // is this wrong?
    cout << x << endl;

    return 0;
}

2- Also this is from an exam sample:

Week & Week::highestSalesWeek(Week aYear[52])
{
  Week max = aYear[0];
  for(int i = 1; i < 52; i++)
  {
    if (aYear[i].getSales() > max.getSales())
      max = aYear[i];
  }
  return max;
}

It asks about the mistake in this code, also how to fix it.

My guess is that it return a local reference. The fix is:

Week & max = aYear[0];

Is this correct/enough?

+5  A: 

The first one is correct.

For the second one, there are infinite number of solutions :), but this would be mine:

Week Week::highestSalesWeek(Week aYear[52]) // return a copy of the week
{ 
  Week max = aYear[0]; 
  for(int i = 1; i < 52; i++) 
  { 
    if (aYear[i].getSales() > max.getSales()) max = aYear[i]; 
  } 
  return max; 
} 

If max is a reference, you would modify the first element of aYear everytime you do:

max = aYear[i]

Also, you could use a pointer to return a reference to the week:

Week & Week::highestSalesWeek(Week aYear[52])
{ 
  Week* max = &aYear[0]; 
  for(int i = 1; i < 52; i++) 
  { 
    if (aYear[i].getSales() > max->getSales()) max = &aYear[i]; 
  } 
  return *max; 
} 
AraK
You were right. I bowed out the shameful way, lol
zildjohn01
+1 for the bow, but I disagree slightly: There's nothing shameful about learning. You'll never make that mistake again. :-)
Thanatos
@AraK Why involve a pointer? A local reference seems preferable.
Jon-Eric
@Jon-Eric A reference won't work. Basically, once you init it, it becomes the array element it self(alias). So, you can't reassign it again.
AraK
@AraK You're right. I missed the assignment at the end of the one-line `if`.
Jon-Eric
+1  A: 

To answer your questions:

foo(x) = 9;   // is this wrong?

I would say yes, it is wrong in that it does not make sense although it is syntactically valid. And as for your "exam" question (who is asking this stuff?):

Week & Week::highestSalesWeek(Week aYear[52])
{
  Week max = aYear[0];
  for(int i = 1; i < 52; i++)
  {
    if (aYear[i].getSales() > max.getSales()) max = aYear[i];
  }
  return max;
}

Well, providing the array dimension on the parameter is pointless, and the code should obviously use a vector. And the correction should be in the signature of the function:

Week  Week::highestSalesWeek(Week aYear[52])

In other words - return a value. You should almost always return values rather than references - references are intended for function parameters.

anon
References as return types come in handy when overloading `operator[]` ;)
FredOverflow
@Fred Of course - that's why I said "almost always". In the users case doing so is pointless.
anon
And overloading `operator=` also, but to be honest, I don't like using assignment as an expression.
FredOverflow
+2  A: 

The important thing about references is always making sure that the reference is not to an object that has gone out of scope.

That is the problem with your second example:

Week & Week::highestSalesWeek(Week aYear[52])
{
  Week max = aYear[0];
  return max;
}

max is an automatic variable local to that method. When that method goes out of scope, max goes out of scope and now your code has a reference to random memory.

Since your code wants to keep reassigning max, you can't use a reference (since after the initial assignment, you can only modify what is referenced, not the reference itself). You need to keep track the actual part of aYear that you want to return a reference to. Two suggestions.

// By pointer
Week & Week::highestSalesWeek(Week aYear[52])
{
  Week *max = &aYear[0];
  ...;
  return *max;
}

// By index
Week & Week::highestSalesWeek(Week aYear[52])
{
  size_t max_idx = 0;;
  ...;
  return aYear[max_idx];
}    
R Samuel Klatchko