Как безопасно скопировать содержимое std::vector в статический массив c-стиля?
Мне нужно манипулировать данными в фиксированном массиве, включающим среднюю вставку.
Вместо использования memcpy и т.д. Я хочу использовать вектор. У меня проблема, когда я хочу
для копирования векторных элементов обратно в массив c-style.
Здесь код:
void tryvector()
{
using namespace std;
const int MAX_SIZE=16;
BYTE myarr[MAX_SIZE]={0xb0,0x45,0x47,0xba,0x11,0x12, 0x4e};
vector<BYTE> myvec (myarr, myarr+MAX_SIZE);
vector<BYTE>::iterator it;
printf("myarr pre :");
for(int i=0;i<MAX_SIZE;++i){
printf("%02x ", myarr[i]) ;
}
printf("\nmyvec pre :")
for(it=myvec.begin(); it<myvec.end();++it){
cout<<hex<<static_cast<int>(*it)<<" ";
}
it = myvec.begin()+ 3;
myvec.insert(it,0x5f);
printf("\nmyvec post:");
for(it=myvec.begin(); it<myvec.end();++it){
cout<<hex<<static_cast<int>(*it)<<" ";
}
copy(myvec.begin(), myvec.end(), myarr); //???
printf("\nmyarr post:");
for(int i=0;i<MAX_SIZE;++i){
printf("%02x ", myarr[i]) ;
}
}
Я использую vs 2005.
Здесь предупреждение:
warning C4996: 'std::_Copy_opt' was declared deprecated
1> c:\program files\microsoft visual studio 8\vc\include\xutility(2270) : see declaration of 'std::_Copy_opt'
1> Message: 'You have used a std:: construct that is not safe. See documentation on how to use the Safe Standard C++ Library'
1> c:\documents and settings\mhd\my documents\tesvector.cpp(50) : see reference to function template instantiation '_OutIt std::copy<std::_Vector_iterator<_Ty,_Alloc>,BYTE*>(_InIt,_InIt,_OutIt)' being compiled
1> with
1> [
1> _OutIt=BYTE *,
1> _Ty=BYTE,
1> _Alloc=std::allocator<BYTE>,
1> _InIt=std::_Vector_iterator<BYTE,std::allocator<BYTE>>
1> ]
Когда я запустил его, я получил следующую ошибку во время выполнения:
Run-Time Check Failure #2 - Stack around the variable 'myarr' was corrupted.
Обратите внимание, что я использую вектор вместо списка или deque, потому что
"средняя вставка", как и код выше, является особой проблемой.
Это произойдет меньше, чем "вставка в конце" и
"случайный доступ к элементу".
Любое решение?
Любой ответ, который напоминает: "Вы используете С++, отбрасываете реализацию массива стиля c.
Использовать только вектор для всей реализации массива "не очень полезно.
Спасибо.
Ответы
Ответ 1
Проблема заключается в том, что вы добавляете вещи в вектор, чтобы в итоге было больше элементов, чем в массиве myarr
, с которым вы его инициализировали.
Если вы хотите скопировать вектор обратно в массив, вам нужно будет его уменьшить:
myvec.resize( MAX_SIZE);
Или вы можете ограничить количество копируемых элементов:
copy( myvec.begin(), myvec.begin()+MAX_SIZE, myarr);
Если вы хотите, чтобы массив myarr
содержал все элементы, он должен быть больше, чем MAX_SIZE
, и вы выяснили, почему люди предлагают использовать vector
вместо сырых массивов (vector
умеют расти, массивы не делают).
Обратите внимание, что пока вы не хотите "Любой ответ, который напоминает:" Вы используете С++, отбрасываете реализацию массива стиля c. Используйте только вектор для всей реализации массива ", вы часто можете избежать использования vector
и передать &myvec[0]
подпрограмм, ожидающих сырой массив. vector
требуется, чтобы сохранить его элементы смежно, как только необработанный массив именно по этой причине.
Поскольку вы получаете предупреждение о небезопасной операции, вы используете компилятор Microsoft. Чтобы исправить проблему безопасно, вы должны использовать алгоритм checked_copy
вместо copy
. Как показано Evgeny Lazin, вы можете создать проверенный итератор для вашего массива, чтобы перейти к алгоритму checked_copy
.
Другими параметрами, чтобы сделать безопасную копию, не требующую расширений Microsoft, было бы объединение массива в класс (возможно, шаблонный), который отслеживает размер массива и предоставляет методы для безопасного копирования данных в массив. Что-то вроде STLSoft array_proxy
template или Boost boost::array
может помочь.
Ответ 2
В общем, я думаю, вы могли бы сделать что-то вроде этого:
void *myarr;
if((myarr = malloc(myvec.size() * sizeof myvec[0])) != NULL)
{
memcpy(myarr, &myvec[0], myvec.size() * sizeof myvec[0]);
/* Do stuff with the C-style array for a while
.
.
.
*/
free(myarr); /* Don't forget handing back the memory when done. */
}
Это выделяет новый массив C-стиля для хранения векторных элементов и копирует данные на месте. Таким образом, нет необходимости сопоставлять размеры статически.
Конечно, это общий, поэтому он просто дает вам void *
для доступа к вашему массиву C, поэтому вам нужно либо сбрасывать, либо просто менять тип на фактический тип (BYTE
в этом случае).
Ответ 3
Вы можете использовать вывод аргумента шаблона для поиска привязки массива:
template<typename T, size_t N>
size_t copy(std::vector<T> const& src, T[N] dest) {
size_t count = std::min(N, src.size());
std::copy(src.begin(), src.begin()+count, dest);
return count;
}
Отключите предупреждения Microsoft о непроверенных материалах. Они нацелены на то, чтобы заманить вас в написание неуправляемого кода.
Ответ 4
Вы можете сделать:
memcpy(myarr, &(myvec)[0], myvec.size())
Изменить: насколько безопасно, согласно this, векторы хранят данные в смежных сегментах памяти, поэтому вы можете получить к ним доступ "не только с использованием итераторов, но и с использованием смещений на обычных указателях на элементы."