Как безопасно скопировать содержимое 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, векторы хранят данные в смежных сегментах памяти, поэтому вы можете получить к ним доступ "не только с использованием итераторов, но и с использованием смещений на обычных указателях на элементы."