T.J.
T.J.

Reputation: 1506

Returning a reference can work?

I used to think returning a reference is bad as our returned reference will refer to some garbage value. But this code works (matrix is a class):

const int max_matrix_temp = 7;
matrix&get_matrix_temp()    
{
   static int nbuf = 0;  
   static matrix buf[max_matrix_temp];  

   if(nbuf == max_matrix_temp)    
      nbuf = 0;  

   return buf[nbuf++];
} 

matrix& operator+(const matrix&arg1, const matrix&arg2)
{  
    matrix& res = get_matrix_temp();
    //...  
    return res;
}

What is buf doing here and how does it save us from having garbage values?

Upvotes: 0

Views: 145

Answers (3)

Matt Lacey
Matt Lacey

Reputation: 8255

buf is declared as static, meaning it retains it's value between calls to the function:

static matrix buf[max_matrix_temp];

i.e. it's not created on the stack as int i = 0; would be (a non-static local variable), so returning a reference to it is perfectly safe.

This following code is dangerous, because the memory for the variable's value is on the stack, so when the function returns and we move back up the stack to the previous function, all of the memory reservations local to the function cease to exist:

int * GetAnInt()
{
  int i = 0;  // create i on the stack
  return &i;  // return a pointer to that memory address
}

Once we've returned, we have a pointer to a piece of memory on the stack, and with dumb luck it will hold the value we want because it's not been overwritten yet — but the reference is invalid as the memory is now free for use as and when space on the stack is required.

Upvotes: 2

Michael Krelin - hacker
Michael Krelin - hacker

Reputation: 143309

I see no buf declared anywhere, which means it doesn't go out of scope with function return, so it's okay. (it actually looks like it's meant to be matrixbuf which is also fine, because it's static).

EDIT: Thanks to R. Martinho Fernandes for the guess. Of course it is matrix buf, so it makes buf static array in which temporary is allocated to make sure it doesn't get freed when the function returns and therefore the return value is still valid.

Upvotes: 0

James Kanze
James Kanze

Reputation: 154047

This is safe up to a point, but very dangerous. The returned reference can't dangle, but if client code keeps it around, at some future point, the client is in for a big surprise, as his value suddenly changes to a new return value. And if you call get_matrix_temp more than max_matrix_temp times in a single expression, you're going to end up overwriting data as well.

In the days before std::string, in code using printf, I used this technique for returning conversions of user defined types, where a "%s" specifier was used, and the argument was a call to a formatting function. Again, max_matrix_temp was the weak point: a single printf which formatted more instances of my type would output wrong data. It was a bad idea then, and it's a worse idea now.

Upvotes: 0

Related Questions