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;
}
Aiden Cullo
  • 105
  • 3
sk patra
  • 457
  • 2
  • 8
  • 12
  • 5
    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
  • @adrianmcmenamin - Its nothing to do with address of function, its about what the function holds.(L-value/R-Value).probably Bart -van Ingen Schenau- is right. – sk patra Jan 31 '14 at 08:32
  • 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;`? – user253751 Jun 21 '17 at 05:31

2 Answers2

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.

Aiden Cullo
  • 105
  • 3
Jeffery Thomas
  • 2,115
  • 1
  • 14
  • 19
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.

Wolf
  • 630
  • 1
  • 6
  • 24
  • 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 09:57