Perché una funzione di ritorno per indirizzo non può essere un lvalue?

5

Perché non è possibile impostare una funzione che restituisce un indirizzo mentre è possibile impostare una funzione che restituisce un riferimento.

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;
}
    
posta sk patra 20.01.2014 - 10:36
fonte

2 risposte

6

Per iniziare, il tuo codice è rotto. Restituire un riferimento o l'indirizzo di una variabile locale restituisce garbage. Non farlo mai. Qui ho riscritto il tuo esempio per restituire qualcosa di reale.

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 questo esempio, xByReference è assegnato al valore 23. xByAddress è assegnato il valore 245. Ovviamente returnByAddress() = &x; non è valido.

La regola è: funzioni restituiscono valori. L'unico modo per risolvere questo è restituire un riferimento.

returnByAddress() restituisce un puntatore per valore. Puoi deferire il puntatore per ottenere un lvalue della cosa puntata.

Seguendo questa regola, puoi restituire un riferimento al puntatore.

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;
}

Questo codice cambia xPointer per puntare all'indirizzo di x .

    
risposta data 26.04.2014 - 17:45
fonte
1

Quello che stai cercando nei tuoi esempi è molto pericoloso.

I risultati della funzione come lvalue possono avere senso, ma è necessario assicurarsi che gli oggetti esistano dopo che la funzione è tornata. Ecco un esempio che rende (kind) un senso:

#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;
}

L'output sarà Hallo world! , dopo che e in buf all'offset 1 è stato modificato in a .

    
risposta data 25.02.2014 - 14:55
fonte

Leggi altre domande sui tag