Предположим, у меня есть std::vector
(назовем это myVec
) размер N
. Какой самый простой способ построить новый вектор, состоящий из копии элементов от X до Y, где 0 <= X <= Y <= N-1? Например, myVec [100000]
через myVec [100999]
вектор размера 150000
.
Если это не может быть эффективно сделано с вектором, есть ли другой тип данных STL, который я должен использовать вместо этого?
Ответы:
Это операция O (N) для создания нового вектора, но на самом деле лучшего способа нет.
источник
O(Y-X)
, либо мы сказали быO(Z) where Z=Y-X
.vector<T> newVec(myVec.begin() + 100000, myVec.begin() + 101000);
?Просто используйте векторный конструктор.
источник
operator[]
возвращает ссылку. Только когда вы прочитаете или напишите ссылку, это станет нарушением прав доступа. Так как мы не делаем ни, но вместо этого получаем адрес, который мы не вызвали UB ,.std::vector<T>(input_iterator, input_iterator)
в вашем случаеfoo = std::vector<T>(myVec.begin () + 100000, myVec.begin () + 150000);
см. например здесьисточник
В наши дни мы используем
span
s! Так что вы бы написали:чтобы получить диапазон из 1000 элементов того же типа, что
myvec
и s. Или более краткая форма:(но мне это не очень нравится, поскольку значение каждого числового аргумента не совсем понятно; и становится еще хуже, если длина и start_pos имеют одинаковый порядок величины.)
В любом случае, помните, что это не копия, это просто представление данных в векторе, поэтому будьте осторожны. Если вам нужна настоящая копия, вы можете сделать:
Ноты:
gsl
обозначает Библиотеку поддержки руководящих принципов. Для получения дополнительной информацииgsl
см .: http://www.modernescpp.com/index.php/c-core-guideline-the-guidelines-support-library .gsl
см .: https://github.com/Microsoft/GSLspan
. Вы бы использовалиstd::span
и,#include <span>
а не#include <gsl/span>
.std::vector
у вас есть gazillion конструкторов, очень легко попасть в тот, который вы не собирались использовать, так что будьте осторожны.источник
cbegin
иcend
только для принципа;) иstd::cbegin
т. д. даже.Если оба не будут изменено (без добавления / удаления элементов - изменение существующих хорошо до тех пор , пока вы обратить внимание на многопоточные вопросы), вы не можете просто пройти вокруг
data.begin() + 100000
иdata.begin() + 101000
, и делать вид , что они являютсяbegin()
иend()
меньшим вектором.Или, поскольку векторное хранилище гарантированно будет смежным, вы можете просто передать массив из 1000 элементов:
Оба эти метода занимают постоянное время, но требуют, чтобы длина данных не увеличивалась, вызывая перераспределение.
источник
Это обсуждение довольно старое, но самое простое еще не упомянуто с инициализацией списка :
Требуется c ++ 11 или выше.
Пример использования:
Результат:
источник
Вы не упомянули, что это за тип
std::vector<...> myVec
, но если это простой тип или структура / класс, который не содержит указателей, и вы хотите добиться максимальной эффективности, то вы можете сделать прямую копию памяти (которая, я думаю, будет быстрее, чем другие ответы предоставлены). Вот общий пример того,std::vector<type> myVec
гдеtype
в этом случаеint
:источник
std::vector(myVec.begin () + 100000, myVec.begin () + 150000);
, разве более длинная версия этого продукта не была бы точно такой же сборкой?std::vector<>(iter, iter)
вmemmove()
, если необходимо (если конструктор тривиален, для подходящего определения тривиала).memcpy
. Сделайте astd::copy
или конструктор, который принимает диапазон (два итератора), и компилятор и std.library сговорются вызыватьmemcpy
при необходимости.Вы могли бы просто использовать
insert
источник
Вы можете использовать копирование STL с производительностью O (M), когда M - это размер субвектора.
источник
newvec.reserve(10100 - 10000);
, Это определенно вариант, и технически это будет работать. Но из двух, которые вы собираетесь рекомендовать?Единственный способ проецировать коллекцию, которая не является линейным временем, - это делать это лениво, где результирующий «вектор» на самом деле является подтипом, который делегирует исходную коллекцию. Например,
List#subseq
метод Scala создает подпоследовательность за постоянное время. Тем не менее, это работает только в том случае, если коллекция является неизменной и если базовый язык использует сборку мусора.источник
Опубликовать это поздно только для других ... Бьюсь об заклад, первый кодер уже сделан. Для простых типов данных копирование не требуется, просто вернитесь к старым добрым методам кода Си.
Затем передайте указатель p и len для всего, что нуждается в подвекторе.
notelen должно быть !!
len < myVec.size()-start
источник
Возможно, array_view / span в библиотеке GSL - хороший вариант.
Вот также реализация одного файла: array_view .
источник
Копирование элементов из одного вектора на другой легко
В этом примере я использую вектор пара , чтобы сделать его легко понять
`
«
Как вы можете видеть, вы можете легко копировать элементы из одного вектора в другой, если вы хотите, например, скопировать элементы из индекса с 10 по 16, мы бы использовали
и если вы хотите, чтобы элементы от индекса 10 до некоторого индекса от конца, то в этом случае
надеюсь, это поможет, просто помните в последнем случае
v.end()-5 > v.begin()+10
источник
Еще один вариант: полезен, например, при перемещении между a
thrust::device_vector
и athrust::host_vector
, где вы не можете использовать конструктор.Также должна быть сложность O (N)
Вы можете комбинировать это с верхним кодом ответа
источник