#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 позже