Копирование массива в std :: vector - PullRequest
8 голосов
/ 15 января 2012

Я искал эту тему и нашел много способов конвертировать массив [] в std :: vector, например, используя:

assign(a, a + n)

или, прямо в конструкторе:

std::vector<unsigned char> v ( a, a + n );

Они решают мою проблему, но мне интересно, можно ли (и правильно) это сделать:

myvet.resize( 10 );
memcpy( &myvet[0], buffer, 10 );

Мне интересно это, потому что у меня есть следующий код:

IDiskAccess::ERetRead nsDisks::DiskAccess::Read( std::vector< uint8_t >& bufferRead, int32_t totalToRead )
{
    uint8_t* data = new uint8_t[totalToRead];
    DWORD totalRead;
    ReadFile( mhFile, data, totalToRead, &totalRead, NULL );
    bufferRead.resize( totalRead );
    bufferRead.assign( data, data + totalRead );
    delete[] data;

    return IDiskAccess::READ_OK;
}

И я бы хотел сделать:

IDiskAccess::ERetRead nsDisks::DiskAccess::Read( std::vector< uint8_t >& bufferRead, int32_t totalToRead )
{
    bufferRead.resize( totalToRead );
    DWORD totalRead;
    ReadFile( mhFile, &bufferRead[0], totalToRead, &totalRead, NULL );
    bufferRead.resize( totalRead );

    return IDiskAccess::READ_OK;
}

(Я удалил обработку ошибок функции ReadFile, чтобы упростить публикацию).

Это работает, но я боюсь, что это не безопасно. Я считаю, что это нормально, так как память, используемая вектором, непрерывна, но я никогда не видел, чтобы кто-то использовал векторы таким образом.

Правильно ли использовать такие векторы? Есть ли другой лучший вариант?

Ответы [ 6 ]

8 голосов
/ 15 января 2012

Да, это безопасно с std::vector Стандарт C ++ гарантирует, что элементы будут храниться в смежных местах памяти.

C ++ 11 Стандарт:

23.3.6.1 Обзор шаблонов классов [vector.overview]

Вектор - это контейнер последовательности, который поддерживает итераторы произвольного доступа. Кроме того, он поддерживает (амортизируется) операции вставки и удаления с постоянным временем в конце; вставить и стереть в середине взять линейное время. Управление хранилищем осуществляется автоматически, хотя могут быть даны подсказки для повышения эффективности. Элементы вектора хранятся смежно , что означает, что если v является вектором, где T является другим типом, отличным от bool, то он подчиняется тождеству & v [n] == & v [0] + n для всех 0 <= n < ВЕРТИКАЛИ (). </p>

5 голосов
/ 15 января 2012

Да, это нормально.Возможно, вы захотите сделать myvet.data() вместо &myvet[0], если это выглядит лучше для вас, но они оба имеют одинаковый эффект.Кроме того, если позволяют обстоятельства, вы можете использовать std::copy вместо этого и иметь большую безопасность типов и все остальные полезности стандартной библиотеки C ++.

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

Убедитесь, что вы не изменяете vector (например, не вызываете push_back для него и т. д.), пока используете указатель, который получаетес data или &v[0], поскольку vector может изменить размер своего буфера на одной из этих операций и сделать недействительным указатель.

3 голосов
/ 15 января 2012

Этот подход верен, он зависит только от вектора, имеющего непрерывную память, которая требуется стандартом.Я считаю, что в C ++ 11 есть новая data() функция-член в векторах, которая возвращает указатель на буфер.Также обратите внимание, что в случае `memcpy вам нужно передать размер в байтах, а не размер массива

2 голосов
/ 15 января 2012

Память в vector гарантированно будет распределена непрерывно, а неподписанный символ - это POD, поэтому абсолютно безопасно memcpy в нее (конечно, при условии, что вы не копируете больше, чем выделили).

1 голос
/ 15 января 2012

Да, решение с использованием memcpy является правильным;буфер, удерживаемый vector, является смежным.Но это не совсем безопасно для типов, поэтому предпочитайте assign или std::copy.

1 голос
/ 15 января 2012

Сначала измените размер , и он должен работать нормально.

vector<int> v;
v.resize(100);
memcpy(&v[0], someArrayOfSize100, 100 * sizeof(int));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...