2012-05-04 32 views
12

Estoy trabajando con 2 bibliotecas. Uno toma y devuelve std::string s mientras que el otro usa std::vector<unsigned char> s.std :: move entre std :: string y std :: vector <unsigned char>

Sería bueno si pudiera robar las matrices subyacentes de std::string y std::vector<unsigned char> y poder moverlas entre sí sin la excesiva copia.

ATM que usar algo como:

const unsigned char* raw_memory = 
    reinterpret_cast<const unsigned char*>(string_value.c_str()), 
std::vector<unsigned char>(raw_memory, raw_memory + string_value.size(); 

Y a la inversa:

std::string(
    reinterpret_cast<const char*>(&vector_value[0]), 
    vector_value.size()); 

Sería mucho mejor ser capaz de definir una:

std::string move_into(std::vector<unsigned char>&&); 
std::vector<unsigned char> move_into(std::string&&); 

Respuesta

7

Esto no es posible.

La clase vector y string no proporcionan manera de robar a otra cosa que vector o stringrespectivamente. No están destinados a intercambiar contenido.

El problema es que vector y string pueden tener representaciones subyacentes muy diferentes. Por lo general, en gcc, por ejemplo, string utiliza la "optimización" anticuada de COW (Copia al escribir), que es muy diferente de la representación típica de vector (por lo general, solo un triple de los atributos de punteros/tamaño_t).

Si está tratando con bytes sin formato, culpe a la biblioteca que decidió ponerlos en string, y refactorícelo si puede.

De lo contrario: copiar. El reinterpret_cast no debería ser necesario porque char y unsigned char tienen conversiones implícitas entre ellos (y ahora char es a menudo unsigned por defecto).

+1

C++ 11 no permite explícitamente copiar en escritura, ¿no es así? A menos que lo mantengan bajo la ley "en tanto se comporte como si cumpliéramos con las especificaciones". Creo que la optimización de cadenas pequeñas ha sido el camino a seguir por un tiempo. –

10

Usted puede usar la inicialización usando iteradores. Eche un vistazo here

EDITAR: pegando el código para que no tenga que ir a ideone. Sigue saliendo del enlace para que pueda jugar con el código

#include <iostream> 
#include <string> 
#include <vector> 
using namespace std; 

int main() { 
     string a = "Hello world"; 
     vector<unsigned char> v(a.begin(), a.end()); 
     for (int i= 0 ;i< v.size(); ++i) { 
      cout << v[i] << endl; 
     } 
     string s(v.begin(), v.end()); 
     cout << s << endl; 
     return 0; 
} 
+1

Por supuesto, esto no es diferente de su solución, con respecto a las copias necesarias (de lo que se trata su pregunta) y por lo tanto no responde a su pregunta de ninguna manera. Sin embargo, es mucho más limpio que su solución, pero un comentario habría sido suficiente para esto. –

+0

@Christian ¿por qué mucho más limpio? 'string & assign (const char * s, size_t n);' debe hacer una memcpy, mientras que 'template string & assign (InputIterator primero, InputIterator last); 'lo emula – Liviu

Cuestiones relacionadas