lo siento por una pregunta tan larga, pero trato de ser lo más claro posible. Esto de alguna manera sigue mi pregunta anterior sobre strings in C++. Estoy intentando descubrir cómo podría devolver std :: string desde una función sin asignaciones de memoria redundante, sin depender de NRVO. Las razones por las que no quiero depender de NRVO son:SWL swap on return?
- no es apoyada por el compilador Actualmente utilizamos
- incluso cuando se admite que no siempre puede ser activado en el modo de depuración
- que podría fallar en algunos casos (example)
Tenga en cuenta que necesito una solución compatible con C++ 03 (sin C++ 0x rvalue referencias de este modo, por desgracia ...)
el SI mplest manera de hacer esto es pasar por referencia y hacer std :: swap, como esto
void test(std::string& res)
{
std::string s;
//...
res.swap(s);
}
Pero es más natural y, a menudo más conveniente para volver por el valor que pasa por referencia, así que lo que quiero lograr es la siguiente:
std::string test()
{
std::string s;
//...
return SOMETHING(s);
}
lo ideal sería que sólo haría un swap
con el "valor de retorno", pero no veo cómo hacer esto en C++. Ya hay auto_ptr que se mueve en lugar de copiar, y realmente podría usar auto_ptr<string>
, pero me gustaría evitar asignar dinámicamente el objeto de cadena en sí.
Mi idea es "etiquetar" de algún modo un objeto de cadena que se devuelve desde una función para permitir mover sus datos cuando se llama a un constructor de copia en el retorno. Así que terminé con este código, que hace exactamente lo que quiero:
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
}
Entonces ... ¿Todo esto tiene sentido, o hay algunos problemas graves que me falta? (No estoy seguro si no hay un problema de por vida, por ejemplo). Tal vez ya has visto esa idea en una biblioteca (libro, artículo ...), ¿y podría darme una referencia?
EDITAR: Como @rstevens notó, este código es específico de MSVC y no se compilará en g ++ que no le gusta el no const temporal. Este es un problema, pero supongamos que esta implementación es específica de MSVC.
No estoy seguro de lo que estás preguntando. ¿Solo necesitas arreglar tu código? Usted dice que hace exactamente lo que quiere pero, por lo que puedo ver, no debería compilarse. –
¿Ha comprobado si su cadena hace COBERTURA? Si es así, habrá pocas asignaciones de memoria adicionales. También algunas implementaciones de std :: string colocarán la cadena en el objeto (cuando la cadena es corta) en lugar de asignarle memoria. Si alguno de estos factores es cierto, sus intentos de optimización pueden aumentar el costo en lugar de reducirlo. –
@Charles: el código está ahí para explicar lo que estoy tratando de lograr, y la pregunta es si lo veo bien y si ya hay algunas buenas implementaciones de eso. –