У меня есть буфер (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 - это размер в символах скопированного буфера.