Domanda

Qualcuno potrebbe spiegare i dettagli in termini di rvalues, lvalues, Baccelli, e non Baccelli il motivo per cui la prima espressione segnata sotto è non ok, mentre la seconda espressione segnata sotto è ok?Nella mia comprensione, sia di tipo int() e() dovrebbe essere rvalues, no?


struct A {};

int main()
{
  int i;
  A a;

  int() = i; //Not OK (error).
  A() = a; //OK.

  return 0;
}

È stato utile?

Soluzione

Rvalues sono ciò che si ottiene dalle espressioni (una semplificazione utile presi per il C standard, ma non è formulato in C++ standardese).Lvalues sono locator valori".Lvalues può essere utilizzato come rvalues.I riferimenti sono sempre lvalues, anche se const.

La differenza principale di cui è necessario essere consapevoli può essere condensato in un unico elemento:non è possibile prendere l'indirizzo di un rvalue (di nuovo, non standardese ma un utile generalizzazione delle regole).O per dirla in altro modo, non è possibile fissare una precisa posizione per un rvalue se si potesse, allora si avrebbe un lvalue.(Tuttavia, è possibile associare un const& a un rvalue per "fissarlo", e 0x sta cambiando le regole drasticamente.)

Tipi definiti dall'utente (Udt), tuttavia sono un po ' speciale:è possibile convertire qualsiasi rvalue in un lvalue, se la classe interfaccia permette di:

struct Special {
  Special& get_lvalue() { return *this; }
};
void f() {
  // remember "Special()" is an rvalue
  Special* p = &Special().get_lvalue(); // even though you can't dereference the
  // pointer (because the object is destroyed), you still just took the address
  // of a temporary

  // note that the get_lvalue() method doesn't need to operate on a const
  // object (though that would be fine too, if the return type matched)
}

Qualcosa di simile sta avvenendo per il tuo A() = a, se non attraverso il compilatore fornito operatore di assegnazione, per girare il rvalue A() in *this.Per citare standard, 12.8/10:

Se la definizione di classe non dichiara esplicitamente una copia operatore di assegnazione, si è dichiarato implicitamente.L'implicitamente dichiarato operatore di assegnazione copia di classe X avrà la forma

X& X::operator=(const X&)

E poi si va avanti con più qualifiche e specifiche, ma l'importante po ' qui.Dato che è una funzione membro, può essere chiamato a rvalues, proprio come Special: get_lvalue può essere, come se si fosse scritto A().operator=(a) invece di A() = a.

Il int() = 1 è esplicitamente vietato, come si è scoperto, perché ints non hanno operator= implementato nello stesso modo.Tuttavia, questo lieve discrepanza tra i tipi non importa in pratica (almeno non ho trovato).


POD significa Pianura Vecchio e di Dati è un insieme di requisiti che specificano utilizzando memcpy è equivalente a copia.Non il CONTENITORE di qualsiasi tipo per il quale non è possibile utilizzare memcpy di copia (naturale opposto del CONTENITORE, niente di nascosto da qui), che tende ad essere la maggior parte dei tipi potrai scrivere in C++.Essere POD o non-POD non cambia di cui sopra, ed è davvero un problema a parte.

Altri suggerimenti

Nella mia comprensione, sia di tipo int() e() dovrebbe essere rvalues, no?

Corretto, il epxression T() è sempre un rvalue per scalare e tipi definiti dall'utente T.Fintanto che non const è coinvolto, l'espressione T() è un modificabile rvalue, per essere più precisi.

Assegnazione coinvolgono tipi scalari richiede un modificabili lvalue sul lato sinistro dell'operatore di assegnazione.Dal int() non è un lvalue, non è possibile assegnare a int().

Per i tipi definiti dall'utente, l'assegnazione è una funzione membro speciale, e le funzioni membro può anche essere chiamato rvalues (vedere §3.10 sezione 10).Ecco perché A().operator=(a) è ben formata.

Ha C ++ fare valore di inizializzazione di un typedef POD? , che cita la standard:

  

L'espressione T (), dove T è un   semplice-type-specificatore (7.1.5.2) per un   non-array tipo di oggetto completa o la   tipo void (possibilmente cv-qualificato),   crea un rvalue del specificato   tipo, che è di valore inizializzato

Quindi int () è un rvalue e non possono essere assegnati a, come si è visto nel primo caso.

A () non sarebbe un simlle-type-specifyer e quindi A () produce un lvalue

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top