/ / Esiste una copia esplicita - c ++, gcc, esplicito-costruttore

Esiste una copia esplicita - c ++, gcc, costruttore esplicito

Sto cercando una sintassi come questa:

class Hugo
{
Hugo();
explicit Hugo( const Hugo& hugo );

Hugo GetRandomHugo()
{
Hugo hugo;
hugo.value = rand();
// this would fail:
//    return hugo;

return Hugo(hugo);        // explicit copy!!
}
};

In altre parole: sto cercando una sintassi di copia esplicita, per consentire ai metodi di restituire una copia, anche se il mio costruttore di copie è esplicito.

Sto usando GCC 4.4.5.

Molte grazie,

charly

risposte:

5 per risposta № 1

Non puoi "t: un ritorno per valore è un implicito costruzione di copie. Qui, il ritorno tenta di copiare implicitamente il tuo temporaneo esplicitamente costruito.

Dall'8 / 12:

L'inizializzazione che si verifica in discussione degli argomenti, funzione di ritorno, lanciare un'eccezione (15.1), gestione un'eccezione (15.3) e elenchi di inizializzatori racchiusi tra parentesi graffe (8.5.1) è chiamato inizializzazione della copia ed è equivalente al modulo:

T x = a;


3 per risposta № 2

Puoi aggirare questo problema avendo un esplicito HugoCopy classe come il seguente

class HugoCopy;
class Hugo {
public:
Hugo() { ... }
Hugo(HugoCopy const&);
explicit Hugo(Hugo const&) { ... }
};

struct HugoCopy {
HugoCopy(Hugo const& hugo)
:hugo(hugo)
{ }

Hugo const& hugo;
};

Hugo::Hugo(HugoCopy const&) { ... }

Ora si applica la seguente semantica

Hugo a;
Hugo b = a; // forbidden
Hugo c(a); // allowed
Hugo d = HugoCopy(a); // allowed

Hugo f() {
Hugo a;
return a; // forbidden
return HugoCopy(a); // allowed
}

In alternativa, è possibile utilizzare una funzione di conversione

class Hugo {
public:
Hugo() { ... }
explicit Hugo(Hugo const&) { ... }
};

struct HugoCopy {
HugoCopy(Hugo const& hugo)
:hugo(hugo)
{ }
operator Hugo const&() { return hugo; }

private:
Hugo const& hugo;
};

Questo si basa su un angolo sottile del C ++linguaggio. Quindi, se lo usi, sai meglio cosa stai facendo o non lo fai: chiama prima la funzione di conversione su HugoCopy (o nel primo caso, il costruttore di Hugo) prendere un Hugo / Hugo const&e poi inizializza diretta la destinazione Hugo oggetto con quello Hugo oggetto. A GCC non piace il codice, ma Clang e Comeau / EDG lo accettano secondo la semantica precedente.


1 per risposta № 3
return Hugo(hugo);

questo crea solo una copia aggiuntiva prima ritorno. La dichiarazione di ritorno effettiva quindi prende quella copia e la copia ancora. L'intero punto nel costruttore della copia è che può essere usato implicitamente, ogni volta che noi o il compilatore abbiamo bisogno di un oggetto copiato.

Se vuoi una sintassi esplicita, puoi semplicemente aggiungere un Clone() o Copy() funzione per la classe, ma non può sostituire il costruttore della copia.

Ogni volta che il compilatore deve copiare un oggetto(ad esempio quando lo si passa in base al valore come parametro della funzione o quando lo si restituisce da una funzione), è necessario creare una copia dell'oggetto. Non è possibile farlo per il compilatore, perché non vedi il codice di "transizione" tra chiamante e chiamante. Puoi copiare l'oggetto in giro all'interno della funzione chiamatao al di fuori di esso, ma non è possibile copiare dal corpo della chiamata al chiamante. Solo il compilatore può farlo e, per farlo, deve essere in grado di copiare l'oggetto a volontà - che viene eseguito tramite il costruttore di copie.