scusate per una domanda così lunga ma cerco di essere il più chiaro possibile. Questo in qualche modo segue la mia domanda precedente su strings in C++. Sto cercando di capire come potrei restituire std :: string da una funzione senza allocazioni di memoria ridondanti, senza fare affidamento su NRVO. I motivi per cui non voglio fare affidamento su NRVO sono:STL swap on return?
- non è supportato dal compilatore attualmente usiamo
- anche quando è supportata potrebbe non sempre essere attivata in modalità debug
- potrebbe non riuscire in alcuni casi (example)
si prega di notare che ho bisogno di una soluzione compatibile C++ 03 (senza C++ 0x rvalue riferimenti in tal modo, purtroppo ...)
Il sI mplest modo fare questo è pass-by-di riferimento e fare std :: di swap, come questo
void test(std::string& res)
{
std::string s;
//...
res.swap(s);
}
Ma è più naturale e spesso più comodo per ritornare al valore di passare per riferimento, quindi quello che voglio raggiungere è questo:
std::string test()
{
std::string s;
//...
return SOMETHING(s);
}
ideale sarebbe basta fare un swap
con il "valore di ritorno", ma non vedo come fare questo in C++. C'è già auto_ptr che si muove invece di copiare, e potrei effettivamente usare auto_ptr<string>
, ma vorrei evitare di allocare dinamicamente l'oggetto stringa stesso.
mia idea è quella in qualche modo "tag" un oggetto stringa che viene riconsegnato da una funzione per consentire lo spostamento suoi dati quando un costruttore di copia è chiamato al ritorno. Così ho finito con questo codice, che fa esattamente quello che voglio:
struct Str
{
struct Moveable
{
Str & ref;
explicit Moveable(Str & other): ref(other) {}
};
Str() {}
Str(const std::string& other) : data(other) {} // copy
Str(Moveable& other) { data.swap(other.ref.data); } // move
Moveable Move()
{
return Moveable(*this);
}
std::string data;
};
Str test()
{
Str s;
//...
return s.Move(); // no allocation, even without NRVO
}
Quindi ... fa tutto questo ha senso, o ci sono alcuni problemi seri che mi manca? (Non sono sicuro che non ci siano problemi di durata, ad esempio). Forse hai già visto questa idea in una biblioteca (libro, articolo ...) e potresti darmi un riferimento?
MODIFICA: come notato da @rstevens, questo codice è specifico per MSVC e non verrà compilato in g ++ che non apprezza il temporaneo non const. Questo è un problema, ma supponiamo che questa implementazione sia specifica per MSVC.
Non sono sicuro di cosa stai chiedendo. Hai solo bisogno di correggere il tuo codice? Dici che fa esattamente quello che vuoi ma, per quanto posso vedere, non dovrebbe essere compilato. –
Hai controllato se la tua stringa fa COW. In tal caso ci saranno alcune allocazioni di memoria aggiuntive. Inoltre alcune implementazioni di std :: string metteranno la stringa nell'oggetto (quando la stringa è breve) piuttosto che allocare memoria per essa. Se ciò è vero, i tuoi tentativi di ottimizzazione potrebbero aumentare il costo piuttosto che ridurlo. –
@Charles: Il codice è lì per spiegare cosa sto cercando di ottenere, e la domanda è se la vedo bene e se ci sono già alcune buone implementazioni di questo. –