Ho visto molti codice implementare la regola del cinque in termini di copia e scambio, ma penso che possiamo usare una funzione di spostamento per sostituire la funzione di scambio come in il seguente codice:Un modo migliore per implementare l'idioma copy-and-swap in C++ 11
#include <algorithm>
#include <cstddef>
class DumbArray {
public:
DumbArray(std::size_t size = 0)
: size_(size), array_(size_ ? new int[size_]() : nullptr) {
}
DumbArray(const DumbArray& that)
: size_(that.size_), array_(size_ ? new int[size_] : nullptr) {
std::copy(that.array_, that.array_ + size_, array_);
}
DumbArray(DumbArray&& that) : DumbArray() {
move_to_this(that);
}
~DumbArray() {
delete [] array_;
}
DumbArray& operator=(DumbArray that) {
move_to_this(that);
return *this;
}
private:
void move_to_this(DumbArray &that) {
delete [] array_;
array_ = that.array_;
size_ = that.size_;
that.array_ = nullptr;
that.size_ = 0;
}
private:
std::size_t size_;
int* array_;
};
Questo codice, penso
- Eccezione sicuro
- richiedono meno di battitura, come molti la funzione basta chiamare move_to_this(), e copiare assegnazione e spostare l'assegnazione sono unificati in un unico singola funzione
- più efficiente di copia-e-swap, come swap coinvolge 3 assegnazioni, mentre qui solo 2, e questo codice non soffre i problemi menzionati in This Link
Ho ragione?
Grazie
Edit:
- Come @Leon sottolineato, forse è necessaria una funzione dedicata per liberare risorse, al fine di evitare la duplicazione del codice in
move_to_this()
e distruttore Come sottolineato @thorsan Per motivi di prestazioni estreme, è meglio separareDumbArray& operator=(DumbArray that) { move_to_this(that); return *this; }
inDumbArray& operator=(const DumbArray &that) { DumbArray temp(that); move_to_this(temp); return *this; }
(grazie a @MikeMB) eDumbArray& operator=(DumbArray &&that) { move_to_this(that); return *this; }
per evitare un movimento extra operatoinDopo l'aggiunta di un po 'di stampa di debug, ho scoperto che nessuna mossa in più è coinvolto in
DumbArray& operator=(DumbArray that) {}
quando si chiama come un incarico mossaCome @Erik Alapää ha sottolineato, è necessario un controllo auto-assegnazione prima
delete
inmove_to_this()
più adatto per [codereview.se]? – cpplearner
Il codice non è eccezionalmente sicuro perché almeno il nuovo e l'eliminazione possono essere lanciati. – Resurrection
@Resurrection, ciò che intendo per "eccezione sicura" non è che non genera eccezioni, ma che anche se viene lanciata un'eccezione, non infrange nulla e rende l'oggetto esistente non valido –