6

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;
}
6
  • 5
    Short answer: You return a pointer by-value and anything returned by-value is (by definition) not an lvalue. Commented Jan 20, 2014 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 Commented Jan 28, 2014 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... Commented Feb 16, 2014 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
    Commented Feb 28, 2014 at 14:56
  • 1
    Why is it not possible to do int x, y; &x = &y;? Commented Jun 21, 2017 at 5:31

2 Answers 2

8

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.

1
  • 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
    Commented Jun 21, 2017 at 9:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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