Breve risposta - non farlo.
Dettagli:
// copy constructor
FeatureValue::FeatureValue(const FeatureValue& other)
{
m_size = other.m_size;
delete[] m_value; // m_value NOT INITIALISED - DON'T DELETE HERE!
m_value = new uint8_t[m_size];
for (int i = 0; i < m_size; i++)
{
m_value[i] = other.m_value[i];
}
}
// assignment operator function
FeatureValue& FeatureValue::operator=(const FeatureValue& other)
{
FeatureValue(other); // error C2082: redefinition of formal parameter
return *this;
}
Note:
- Quando il costruttore di copia viene chiamato, è la costruzione del nuovo oggetto con riferimento all'oggetto la copia, ma il costruttore di default non eseguito prima della copia costruttore. Ciò significa che
m_value
ha un valore indeterminato quando il costruttore di copie si avvia, è possibile assegnarlo, ma leggere da esso è un comportamento indefinito e a delete[]
è notevolmente peggiore (se qualcosa può essere peggiore di UD! ;-)). Quindi, lascia fuori quella linea delete[]
.
Poi, se operator=
cerca di sfruttare la funzionalità dal costruttore di copia, deve rilasciare prima i dati esistenti m_value
sta indicando o sarà trapelato. La maggior parte delle persone cercano di farlo nel modo seguente (che è rotto) - Credo che questo sia quello che stavi cercando per:
FeatureValue& FeatureValue::operator=(const FeatureValue& other)
{
// WARNING - this code's not exception safe...!
~FeatureValue(); // call own destructor
new (this) FeatureValue(other); // reconstruct object
return *this;
}
Il problema di questo è che se la creazione di FeatureValue fallisce (ad esempio perché new
può 't ottenere la memoria desiderata), quindi l'oggetto FeatureValue
viene lasciato con uno stato non valido (ad esempio m_value
potrebbe essere puntato nello spazio). Successivamente, quando il distruttore viene eseguito e fa un delete[] m_value
, si ha un comportamento indefinito (il programma si bloccherà probabilmente).
Si dovrebbe davvero affrontare questo più sistematicamente ...o scrivendo fuori, passo dopo passo, o forse l'attuazione di un metodo garantito non gettare swap()
(facile da fare ... basta std::swap()
m_size
e m_value
, e usarlo ala:
FeatureValue& FeatureValue::operator=(FeatureValue other)
{
swap(other);
return *this;
}
che è facile e pulito, ma ha un paio di piccoli problemi di prestazioni/efficienza:
mantenendo qualsiasi m_value
array esistente più a lungo del necessario, aumentare l'utilizzo della memoria di picco ... si potrebbe chiamare clear()
In pratica, la maggior parte dei programmi non banali non mi importerebbe. su questo a meno che il dat una struttura in questione conteneva enormi quantità di dati (ad es. centinaia di megabyte o gigabyte per un'app per PC).
nemmeno cercando di riutilizzare la memoria esistente m_value
- invece sempre fare un altro new
per other
(che può portare a ridurre l'utilizzo della memoria, ma non è sempre la pena).
In definitiva, le ragioni non ci può essere distinto costruttore di copia e operator=
- piuttosto che avere il compilatore crea automaticamente uno dall'altro - è che le implementazioni ottimale efficienti possono non - in generale - leva reciprocamente in modo speravi.
fonte
2013-07-05 03:05:45
perché non solo "m_valore [i] = altro.m_valore [i]" invece di utilizzare il valore intermedio, ad es. 'valore [i] = altro.m_valore [i]'? – stackunderflow