Скопировать содержимое std::vector в буфер символов *?

#c #stl #stdvector

#c #stl #stdvector

Вопрос:

У меня есть std::vector. Я хочу скопировать содержимое вектора в буфер символов * определенного размера.

Есть ли безопасный способ сделать это?

Могу ли я это сделать?

 memcpy(buffer, _v.begin(), buffer_size);
  

или это?

 std::copy(_v.begin(), _v.end(), buffer); // throws a warning (unsafe)
  

или это?

 for (int i = 0; i < _v.size(); i  )
{
  *buffer = _v[i];
  buffer  ;
}
  

Спасибо..

Комментарии:

1. Мой C -fu немного заржавел, но не char* str = amp;_v[0]; справился бы с этой задачей?

2. Вероятно, @Polynomial, по крайней мере, на первых порах. Если вектор когда-либо перераспределит свой буфер, местоположение может измениться, и если вектор уничтожен, указатель недействителен. Это настолько рискованно, что, вероятно, это не хорошая идея.

3. @Polynomial: Это не приведет к копированию вектора в другой буфер, это просто захватит адрес внутреннего буфера в векторе.

4. @Polynomy: На данный момент это будет работать отлично и даже намного быстрее, однако это приведет к сбою в тот момент, когда вы добавите некоторые данные в вектор и превысите его емкость. В это время он выделит новый блок и освободит тот, на который вы указываете.

5. Реальный вопрос в том, почему вы хотите использовать char* буфер? std::vector намного лучше (почти) во всех отношениях.

Ответ №1:

 std::copy(_v.begin(), _v.end(), buffer);
  

Это предпочтительный способ сделать это в C . Безопасно копировать таким образом, если buffer достаточно большой.

Комментарии:

1. Этого недостаточно: вы должны добавить символ в конце.

2. @AdamZalcman: Это неразумно. Что, если вектор содержит много ?

3. @AdamZalcman: Кроме того, если это разумно, то первоначальный выбор std::vector<char> изначально неверен, поскольку std::string было бы лучшим выбором в случае, если char* необходимо обработать с помощью c-string.

4. @AdamZalcman: Нет. Я не думаю, что это неаккуратный ответ. Когда я вижу std::vector<char> вместо std::string , я предполагаю, что содержимое вектора не гарантированно является c-строкой.

5. @krebstar: Да. vector<char> гарантируется, что это непрерывный блок памяти?.

Ответ №2:

Если вам просто нужно char* , то вы можете сделать это:

 char *buffer=amp;v[0];//v is guaranteed to be a contiguous block of memory.
//use buffer
  

Обратите внимание, что изменение данных, на которые указывает buffer , также изменяет содержимое вектора!

Или, если вам нужна копия, выделите память размером, равным v.size() байтам, и используйте std::copy :

  char *buffer = new char[v.size()];
 std::copy(v.begin(), v.end(), buffer);
  

Не забудьте сделать это delete []buffer; после того, как закончите, иначе произойдет утечка памяти.

Но тогда зачем вам создавать такую проблему, которая требует, чтобы вы сами управляли памятью .. особенно, когда вы можете сделать лучше, например:

 auto copy = v; // that's simpler way to make copies!!
// and then use copy as new buffer.
// no need to manually delete anything. :-)
  

Надеюсь, это поможет.

Ответ №3:

Самый безопасный способ скопировать a vector<char> в char * буфер — скопировать его в другой вектор, а затем использовать внутренний буфер этого вектора:

 std::vector<char> copy = _v;
char * buffer = amp;copy[0];
  

Конечно, вы также можете получить доступ к _v буферу s, если вам на самом деле не нужно копировать данные. Кроме того, помните, что указатель будет признан недействительным, если изменить размер вектора.

Если вам нужно скопировать его в определенный буфер, то перед копированием вам нужно убедиться, что буфер достаточно велик; для массивов нет проверок границ. После того, как вы проверили размер, ваш второй метод является лучшим. (Первый работает, только если vector::iterator это указатель, что не гарантируется; хотя вы могли бы изменить второй аргумент на amp;_v[0] , чтобы заставить его работать. Третий делает то же самое, но более сложный, и, вероятно, его следует исправить, чтобы он не изменялся buffer ).

Комментарии:

1. Это почти лучше всего. Я так не думал. 1.

2. короче говоря: остерегайтесь такого случая: char * buffer;{std::vector<char> copy = _v;buffer = amp;copy[0];} cout<<buffer;

3. @test30 Чтобы уточнить, было бы полезно указать, что проблема, о которой вы предупреждаете, заключается в том, что вектор копирования находится внутри вложенной области. Вектор копирования освобождается при закрытии области видимости. Если вы удалите область с фигурными скобками, это работает нормально. (Учитывая, что это вопрос уровня неспециалиста.)

Ответ №4:

Ну, вы хотите присвоить *buffer для случая 3, но это должно сработать. Первый вариант почти наверняка не сработает.

РЕДАКТИРОВАТЬ: я придерживаюсь исправления относительно # 2.

Комментарии:

1. В любом случае, нет ли более быстрого способа сделать это? выполнение цикла for / while кажется странным .. =/

Ответ №5:

 static std::vector<unsigned char> read_binary_file (const std::string filename)
{
    // binary mode is only for switching off newline translation
    std::ifstream file(filename, std::ios::binary);
    file.unsetf(std::ios::skipws);

    std::streampos file_size;
    file.seekg(0, std::ios::end);
    file_size = file.tellg();
    file.seekg(0, std::ios::beg);

    std::vector<unsigned char> vec(file_size);
    vec.insert(vec.begin(),
               std::istream_iterator<unsigned char>(file),
               std::istream_iterator<unsigned char>());
    return (vec);
}
  

и затем:

 auto vec = read_binary_file(filename);
auto src = (char*) new char[vec.size()];
std::copy(vec.begin(), vec.end(), src);
  

но не забудьте удалить [] src позже