2

Here's an example:

void foo(int*& x) {}

struct boo  
{  
  int* z;  
  int* getZ() { return z; }  
};

int main()
{
  int* y;
  foo(y);  // Fine

  boo myBoo;
  foo(myBoo.getZ());  // Won't compile

  return 0;
}

I can fix this by having boo::getZ() return a reference to a pointer, but I'm trying to understand what the difference is between the two parameters being passed in to foo(). Is the int* being returned by boo::getZ() not an lvalue? If so, why not?

  • 1
    getZ() returns a pr-value. Remember that a pointer *is* a value which can be passed around and in this case it is returning a copy of the pointer z. foo() of course wants to take a reference to a pointer, and so there is a problem because getZ() is returning a temporary. – qeadz Jul 10 '14 at 21:47
  • Do you want `foo` to be able to modify `myBoo.z` ? – M.M Jul 10 '14 at 22:41
  • Thanks for the answers. For anyone else having the same problem, you might try reading this post: http://stackoverflow.com/questions/3601602/what-are-rvalues-lvalues-xvalues-glvalues-and-prvalues – user3827224 Jul 11 '14 at 11:57

2 Answers2

9

If T is an object type and f is declared as...

T &  f();                                          f() is an lvalue
T && f();                     then                 f() is an xvalue
T    f();                                          f() is a prvalue

So getZ() is a prvalue (T = int *), which is an rvalue, and not an lvalue.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
2

"Is the int* being returned by boo::getZ() not an lvalue? If so, why not?"

No, think twice! The return value of a function is a prvalue unless a reference is returned.

You need

struct boo {  
   int* z;  
   int& getZ() { return *z; }
   // ^ 
   // |------------- Note the reference '&'
};

to compile this correctly.

Though having something like

struct boo {  
   int& getZ() { return z; }

private:
   int z;  
};

feels better for me (though not right finally IMHO).


What I'd have for really providing getter/setter member functions, would look as follows (Note it's pseudo code, replace T with the actual data types you need!)

class boo {  
public:
   T z() const { return z_; }
   void z(const T& newValue ) { z_ = newValue; }

private:
   T z_;  
};
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • This will allow `foo` to modify `myBoo.z` (OP was unclear but it seems to me that his intent was for `getZ` to return a copy by value) – M.M Jul 10 '14 at 22:33
  • @MattMcNabb I have clearly stated, how I think it should look like for correct getter/setter semantics. – πάντα ῥεῖ Jul 10 '14 at 22:35
  • IMO correct getter semantics is returning `T`, not `const T&`. (and neither of them can be given to OP's `foo`). `const T&` can be used as a workaround if copying `T` is undesirable, but that's not a problem where `T` is a primitive type as in this case. – M.M Jul 10 '14 at 22:40
  • @MattMcNabb Good point, I wanted to make it as generic as possible. You're probably right, copy elision will do it's job correctly. I'm fixing ... – πάντα ῥεῖ Jul 10 '14 at 22:44