A () = A () - perché si compila?


85
class A {};

int main() {
 A() = A();
 return 0; 
}

Perché questo codice viene compilato? Non dovrebbe esserci qualche errore che sul lato sinistro dell'assegnazione dell'operatore dovrebbe essere posizionato lvalue? È A () lvalue? versione g ++ 4.7

Risposte:


88

Per i tipi incorporati, avresti ragione: l'operatore di assegnazione integrato richiede un lvalue modificabile sul lato sinistro.

Tuttavia, questo non utilizza l'operatore incorporato, ma il sovraccarico dichiarato implicitamente dalla classe. Questa è una funzione membro, equivalente a

A().operator=(A());

e le funzioni membro possono essere chiamate su rvalues .


7
non è l'inizializzazione della copia?
polvere di stelle

13
@Named: No, è l'assegnazione non l'inizializzazione.
Mike Seymour

1
@ paul23: È vero (supponendo che tu operator=non intenda operator()), ma non ha molto a che fare con la domanda. L'esempio non fa nulla con il risultato del compito.
Mike Seymour

3
@ paul23 A()non chiama operator(), costruisce un oggetto di tipo A.
Interjay

3
Non può essere un'inizializzazione perché non c'è dichiarazione.
Kos

32

Se vuoi davvero, puoi farlo non compilare con C ++ 11:

class A {
    template <typename T>
    void operator=(T&&) && = delete; // no op= for rvalues

    // generate other special members normally
    A() = default;
    A(A const&) = default;
    A(A&&) = default;
    ~A() = default;
    // op= only for lvalues
    A& operator=(A&&) & = default;
    A& operator=(A const&) & = default;
};

int main() {
 A() = A(); // error
 return 0; 
}

( esempio dal vivo )

Notare i simboli &e &&( noti anche come qualificatori ref) alla fine delle dichiarazioni dei vari operator=moduli. Questo fa sì che quelle dichiarazioni siano selezionate rispettivamente per lvalues ​​e rvalues. Tuttavia, la versione rvalue, quando selezionata dalla risoluzione dell'overload, fa sì che il programma sia mal formato perché viene eliminato.

L'operatore predefinito = generato, tuttavia, non ha alcun qualificatore ref, il che significa che può essere chiamato sia per lvalues ​​che per rvalues; ecco perché il codice nella domanda viene compilato, anche se A()è un valore.


1

Il compilatore C ++ fornisce a tutte le classi un costruttore predefinito, questo è ciò che accade, rispetto al codice, quando dici A () = A (); richiama semplicemente il costruttore con un oggetto senza nome e la funzione restituisce il riferimento all'oggetto costruito (implicito). Questo è tutto...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.