5

Why is it not possible to set a function returning an address while it is possible to set a function that returns a reference.

int* returnByAddress()
{
    int x = 20;
    return &x;
}

int& returnByReference()
{
    int x = 30;
    return x;
}

int main()
{
    returnByReference() = 23; // possible
    int x = 23;
    returnByAddress() = &x;   // not a lvalue error 
    *returnByAddress() = 245; // possible

    return 0;
}
  • 4
    Short answer: You return a pointer by-value and anything returned by-value is (by definition) not an lvalue. – Bart van Ingen Schenau Jan 20 '14 at 10:44
  • 1
    This is seriously bizarre code, but I'd suggest that for the returned reference it is that which is set to 23, the returnByAdress() line looks like an attempt to set the address of the function – adrianmcmenamin Jan 28 '14 at 13:02
  • 2
    Aside from why it does or does not work, why would you ever write such code? This code is ugly and hard to read and that is where bugs go to hide... – EricSchaefer Feb 16 '14 at 18:08
  • 2
    The code is bugged (besides the lvalue compile-time failure regarding the lvalue).Make the int x variables static in the 2 functions, because you are using references/pointers to variables that cease to exist when the functions exit. – Bgie Feb 28 '14 at 14:56
  • 1
    Why is it not possible to do int x, y; &x = &y;? – immibis Jun 21 '17 at 5:31
6

To start off, your code is broken. Returning a reference or the address of a local variable is returning garbage. Never do this. Here I've rewritten your example to return something real.

int xByAddress = 20;
int xByReference = 30;

int* returnByAddress()
{
    return &xByAddress;
}

int& returnByReference()
{
    return xByReference;
}

int main()
{
    returnByReference() = 23; //possible
    int x = 23;
    returnByAddress() = &x; //not a lvalue error 
    *returnByAddress() = 245; //possible

    return 0;
}

In this example, xByReference is assigned the value 23. xByAddress is assigned the value 245. Of course, returnByAddress() = &x; is invalid.

The rule is: functions return rvalues. The only way around this is to return a reference.

returnByAddress() returns a pointer by rvalue. You can deference the pointer to get an lvalue of the thing pointed at.

Following this rule, you can return a reference to the pointer.

int xByAddress = 20;
int *xPointer = nullptr;

int*& returnByPointerReference()
{
    xPointer = &xByAddress;
    return xPointer;
}

int main()
{
    int x = 23;
    returnByPointerReference() = &x; //not a lvalue error     
    return 0;
}

This code changes xPointer to point at the address of x.

1

What you are trying in your examples is very dangerous.

Function results as lvalues can make sense, but you have to ensure that the objects exist after the function returns. Here an example that makes (kind of) sense:

#include <iostream>

/// get a R/W reference to a byte in a buffer
/// Warning: no range checking is performed
unsigned char& refByteOfBuffer(void* buf, const int offset)
{
    return reinterpret_cast<unsigned char*>(buf)[offset];
}

void testRefWrite()
{
    unsigned char buf[] = "Hello world!";
    refByteOfBuffer(buf, 1) = 'a';
    std::cout << buf << std::endl;
}

The output will be Hallo world!, after the e in buf at offset 1 was changed to a.

  • And the real danger is that it might not do anything obviously wrong when you try it at home, but is guaranteed to turn into a nasty and hard to find bug eventually. – gnasher729 Jun 21 '17 at 9:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.