2013-08-14 15 views
10
class C{ 
    //methods and properties 
} 

void C::some_method(C* b){ 
    delete this; 
    this = b;  
} 

Questo mi dà l'errore follwing durante la compilazione:cambiamento 'questo' puntatore di un oggetto al punto oggetto diverso

error: lvalue required as left operand of assignment 

La mia intenzione: dire che ci sono oggetti A e B della classe C. il contenuto della classe C può essere molto grande e la copia campo per campo può essere molto costosa. Voglio che tutti i contenuti di 'a' siano sostituiti da b in modo economico.

Il costruttore di copie predefinito esegue l'operazione desiderata?

Ho trovato qualcosa chiamato 'mossa costruttore' http://akrzemi1.wordpress.com/2011/08/11/move-constructor/

Forse, si potrebbe ottenere l'effetto che voglio.

+0

sei sicuro di poter fare qualcosa del genere ?? – DonCallisto

+15

Così fa. Hai appena scoperto che "questo" non è riassegnabile perché * non avrebbe alcun senso *. Avete una domanda? –

+0

'questo 'non può essere modificato. Qual è l'obiettivo di livello superiore che stai cercando di raggiungere? –

risposta

12

Il this -pointer è un puntatore implicito all'oggetto nel cui contesto si sta lavorando, non è possibile riassegnarlo.

Secondo la bibbia di Stroustrup (The C++ Programming Language, 3 ° edizione che ho) this è espresso come

C * const this 

significa che hanno una costante puntatore alla classe C, in modo che il compilatore si lamenta se provi a cambiarlo

EDIT:

Come è stato corretto, l'espressione sopra citata non descrive this completamente corretto, per this è in realtà un rvalue.

+0

Non ero sicuro se 'this' è const, grazie per il informazione. – EarlGrey

+0

Si può anche andare sopra e avere un puntatore 'this' su un oggetto costante, ottenendo' const C * const this' –

+1

La citazione dice come è "implementata". Formalmente, "questo" non è un oggetto; è un'espressione di valore. –

15

Non è possibile modificare i punti this. Non saprei nemmeno perché vorresti farlo.

+1

@kol In realtà non è possibile, a meno che il tuo compilatore non sia seriamente rotto (o seriamente vecchio --- potresti farlo fino a poco prima del 1990, quando alla lingua è stata aggiunta la possibilità di sovraccaricare l'operatore new). –

6

Non è possibile assegnare un valore diverso a this poiché punta all'oggetto stesso e questo non ha alcun senso. Puoi istanziare un nuovo oggetto e usare il suo implicito questo puntatore.

Inoltre, se si tenta di fare una copia di oggetto, è possibile sovrascrivere operator=

class Foo 
{ 
    public: 
    [...] 
    Foo& operator=(const Foo& foo); 
} 

int main() 
{ 
Foo foo; 
foobar = foo; //invoke operator= overwrited method 
} 


1

L'errore dice: "Non è possibile assegnare a bthis". Per quanto ne so, lo this è qualcosa che non puoi cambiare, perché non è un puntatore reale, ma un riferimento personale.

+0

È un puntatore, è fondamentalmente 'ClassType * const this', il che significa che non può essere modificato per puntare a qualcos'altro, e dal momento che è un valore non può essere sul lhs di un'espressione. – Rapptz

+1

@Rapptz Ha un tipo di puntatore, ma _isn't_ const, poiché è un valore di rvalore, mentre i valori rval di tipo non di classe non hanno qualificatori di cv. –

+0

Qual è un altro esempio di un valore rval di tipo non di classe? –

14

citare la norma:

Nel corpo di una funzione membro non statica (9.3), la parola this è un'espressione prvalue cui valore è l'indirizzo dell'oggetto per cui la funzione è chiamato.

A "prvalue" è una rvalue puro, qualcosa di simile a 42 o 3.14159. Allo stesso modo non è possibile fare qualcosa come 42 = x, non è possibile assegnare a this; in entrambi i casi (almeno concettualmente), lo non è un oggetto il cui valore può cambiare.

E sono davvero curioso di sapere cosa ci si aspetta di accadere se scrivo qualcosa come:

int 
main() 
{ 
    C c1; 
    C c2 
    c1.some_method(&c2); 
} 

Si aspetta l'indirizzo del c1 in qualche modo miracolosamente cambiamento, e per c1 e c2 a essere alias allo stesso oggetto? (Ed c1.some_method(NULL) è ancora più intreguing.)

+2

@kol In realtà, non è possibile, e la tua risposta è semplicemente errata. Lo standard è abbastanza chiaro qui: 'this' è un valore di prvalue (o un valore in pre-C++ 11), e l'assegnazione ad un valore di rvalue è illegale, e c'è un modo _no_ per ottenere un lvalue da un valore di non classe genere. –

+0

@JamesKanze Sì, voglio che siano alias. –

+0

@UtkristAdhikari Ma questo è manifestamente impossibile, dal momento che il codice in una funzione membro non può cambiare il significato di un simbolo in 'main'. In 'main',' c1' indica un'entità molto specifica e il simbolo di associazione -> entity è gestito interamente dal compilatore e dal linker, al momento della compilazione e del collegamento. –

0

basta utilizzare il solito approccio, invece di magia nera e UB:

C* c1 = new C(); 
C* c2 = new C(); 

// do some work perhaps ... 

delete c1; 
c1 = c2; 

Ora c1 è un alias per c2 come si voleva. Fai attenzione però quando pulisci la memoria in modo da non eliminare due volte un oggetto. Potresti forse considerare i puntatori intelligenti ...

+0

l'assegnazione deve avvenire all'interno del metodo di c1 –

+0

Questo codice non è il solito approccio per nulla. Se volessi c1 puntare allo stesso oggetto di c2, non c'è motivo di novità ed elimina un oggetto per c1. Basta assegnare immediatamente c2 a c1. Inoltre, naked new e delete non sono eccezionalmente sicuri (la sicurezza delle eccezioni è importante anche se non si utilizza il meccanismo di gestione delle eccezioni C++ integrato). Per lo meno, usa un unique_ptr per contenere l'oggetto assegnato dinamicamente. Ma a meno che tu non abbia una buona ragione, non dovresti allocare dinamicamente in primo luogo. Il solito approccio per creare un alias è attraverso un riferimento. – suncho

Problemi correlati