2012-05-04 5 views
12

Я работаю с 2 библиотеками. Один берет и возвращает std::string s, а другой использует std::vector<unsigned char> s.std :: перемещение между std :: string и std :: vector <unsigned char>

Было бы хорошо, если бы я мог украсть базовые массивы от std::string и std::vector<unsigned char> и иметь возможность перемещать их друг в друга без чрезмерного копирования.

ATM Я использую что-то вроде:

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

И другой путь:

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

Было бы гораздо лучше, чтобы быть в состоянии определить:

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

ответ

7

Это невозможно.

vector и string класс не обеспечивают способ украсть от всего остального, чем vector или stringсоответственно. Они не предназначены для обмена контентом.

Проблема заключается в том, что vector и string могут иметь самые разные базовые представления. Как правило, в gcc, например, string используют старую «оптимизацию» COW (Copy On Write), которая сильно отличается от типичного представления vector (обычно это всего лишь тройка атрибутов указателей/размер_t).

Если вы имеете дело с необработанными байтами, обвините библиотеку, которая решила поместить их в string, и реорганизовать ее, если сможете.

В противном случае: копировать. reinterpret_cast не требуется, так как char и unsigned char имеют неявные отливки между ними (а теперь char часто unsigned по умолчанию).

+1

C++ 11 явно запрещает копирование при записи, не так ли? Если они не держат его под «до тех пор, пока он ведет себя так, как если бы мы соблюдали закон спецификации». Я думаю, что небольшая оптимизация строк - это то, что нужно сделать некоторое время. –

10

You может использовать инициализацию с использованием итераторов. Посмотрите here

EDIT: вставьте код, чтобы вам не нужно было идти идеон. Все еще оставляя ссылку так, чтобы вы могли играть в арку с кодом

#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

Конечно, это не отличается от его решения, касающегося необходимых копий (о чем идет речь) и, таким образом, никоим образом не отвечает на его вопрос. Тем не менее, он намного чище, чем его решение, но для этого было бы достаточно комментариев. –

+0

@Christian, почему много чище? 'string & assign (const char * s, size_t n);' должен делать memcpy, а 'template string & assign (InputIterator first, InputIterator last); 'эмулирует его – Liviu