2012-05-04 2 views
12

Je travaille avec 2 bibliothèques. On prend et retourne std::string s alors que l'autre utilise std::vector<unsigned char> s.std :: déplacer entre std :: string et std :: vector <unsigned char>

Ce serait bien si je pouvais voler les tableaux sous-jacents de std::string et std::vector<unsigned char> et être en mesure de les déplacer les uns dans les autres sans la copie excessive.

ATM-je utiliser quelque chose comme:

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(); 

Et dans l'autre sens:

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

Il serait beaucoup mieux d'être en mesure de définir un:

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

Répondre

7

Ceci n'est pas possible.

La classe vector et string ne fournissent pas moyen de voler quoi que ce soit d'autre que vector ou stringrespectivement. Ils ne sont pas destinés à échanger du contenu.

Le problème est que vector et string peuvent avoir des représentations sous-jacentes très différentes. Typiquement dans gcc par exemple, string utilise l'ancienne "optimisation" COW (Copy On Write), qui est très différente de la représentation typique vector (généralement juste un triple des attributs pointeurs/size_t). Si vous traitez avec des octets bruts, blâmer la bibliothèque qui a décidé de les mettre dans string, et refactoriser si vous le pouvez.

Sinon: copier. Le reinterpret_cast ne devrait pas être nécessaire car char et unsigned char ont des conversions implicites entre eux (et maintenant char est souvent unsigned par défaut).

+1

C++ 11 interdit explicitement la copie sur l'écriture, n'est-ce pas? À moins qu'ils ne le gardent sous le «tant qu'il se comporte comme si nous nous conformions à la loi». Je pense que l'optimisation de petites chaînes a été la voie à suivre pendant un certain temps. –

10

Vous peut utiliser l'initialisation en utilisant des itérateurs. Jetez un coup d'œil here

EDIT: en collant le code de sorte que vous n'ayez pas à aller à ideone. Toujours en laissant le lien de sorte que vous pouvez jouer avec le code

#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

Bien sûr, ce n'est pas différent de sa solution, en ce qui concerne les copies nécessaires (quelle est sa question) et ne répond donc pas à sa question en aucune façon. C'est beaucoup plus propre que sa solution, mais un commentaire aurait suffi pour cela. –

+0

@ Christian pourquoi beaucoup plus propre? 'string & assign (const char * s, taille_t n);' devrait faire un memcpy, alors que 'template chaîne & assign (InputIterator first, InputIterator last); 'l'émule – Liviu

Questions connexes