Преобразование (void *) в std::vector <unsigned char>

У меня есть буфер (void*), который мне нужно преобразовать в std::vector<unsigned char>, прежде чем я смогу передать его. К сожалению, мои навыки каста С++ немного слабые. Любые предложения?

Ответ 1

Вам понадобится длина буфера. Как только вы это сделаете, мы можем это сделать:

unsigned char *charBuf = (unsigned char*)voidBuf;
/* create a vector by copying out the contents of charBuf */
std::vector<unsigned char> v(charBuf, charBuf + len);

Хорошо, в комментарии мне стало известно, почему я не использовал reinterpret_cast:

  • В С++ листинг C-стиля - это функция удобства - он просит компилятор выбрать самую безопасную и самую переносимую форму преобразования по множеству доступных операторов трансляции.

  • reinterpret_cast определяется реализацией и всегда должна быть последней вещью в вашем уме (и использоваться, когда вы обязательно занимаетесь непереносимой вещью сознательно).

  • Преобразование между (unsigned не изменяет тип) char * и void * переносимо (вы действительно можете использовать static_cast, если вы действительно придирчивы).

Проблема с литой C-стилем: добавленная гибкость может вызывать страдания при изменении типа указателя.

Примечание: Я согласен с общим соглашением о том, чтобы не бросать как можно больше. Однако, без какого-либо источника, это лучшее, что я мог сделать.

Ответ 2

Вы не можете просто отличить void* от std::vector<unsigned char>, потому что макет памяти последнего включает в себя другие объекты, такие как размер и количество выделенных в настоящее время байтов.

Предполагая, что на буфер указано значение buf, а его длина n:

vector<unsigned char> vuc(static_cast<char*>(buf), static_cast<char*>(buf) + n);

создаст копию буфера, которую вы можете безопасно использовать.

[EDIT: добавлен static_cast<char*>, который необходим для арифметики указателя.]

Ответ 3

Вы не должны делать кастинг - полный стоп. Пожалуйста, разместите код, который иллюстрирует ваш вопрос. Я действительно не понимаю, что вы подразумеваете под буфером (void *).

Ответ 4

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

void SomeFunc(void* input);

main() {
  std::vector< unsigned char > v;
  SomeFunc((void*) &v);
}

SomeFunc(void* input) {
  // Now, you could cast that void* into a vector
  std::vector< unsigned char >* v_ = (vector<unsigned char>*)input
}

Я на самом деле не пытался увидеть, будет ли это работать, но в том духе этого. Тем не менее, если вы делаете это с нуля, вы определенно делаете это неправильно. Это действительно плохо. Единственный раз, когда это может быть даже отдаленно понятно, - если вы вынуждены реализовать уже определенный "SomeFunc()".

Ответ 5

с использованием класса std::vector для уже выделенного буфера не является решением. Объект std::vector управляет памятью и освобождает ее во время уничтожения.

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

Если у вас есть этот буфер void *, связанный через некоторые функции API C, вы можете забыть о преобразовании в std::vector.

Если вам нужна только копия этого буфера, это можно сделать следующим образом:

std::vector< unsigned char> cpy( 
    (unsigned char*)buffer, (unsigned char*)buffer + bufferSize);

где bufferSize - это размер в символах скопированного буфера.