Преобразование (void *) в std :: vector <unsigned char> - PullRequest
12 голосов
/ 07 апреля 2009

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

Ответы [ 5 ]

25 голосов
/ 07 апреля 2009

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

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 ++ приведение в стиле C - это удобная функция - она ​​просит компилятор выбрать наиболее безопасную и наиболее переносимую форму преобразования из набора доступных операторов преобразования.

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

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

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

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

3 голосов
/ 07 апреля 2009

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

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 ()».

3 голосов
/ 07 апреля 2009

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

3 голосов
/ 07 апреля 2009

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

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

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

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

[РЕДАКТИРОВАТЬ: Добавлено static_cast<char*>, что необходимо для арифметики указателя.]

2 голосов
/ 07 апреля 2009

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

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

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

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

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

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

...