address
, inspect
и object_size
в пакете pryr могут быть полезны здесь.
library(pryr)
address(df)
## [1] "0x7e0b688"
inspect(df)
## <VECSXP 0x7e0b688>
## <REALSXP 0x7e0d028>
## <INTSXP 0x96e7278>
## ...snip...
Например, пространство, занимаемое L1
, плюс пространство, занятое L2
, больше, чем пространство, занимаемое ими обоими, так очевидно, что происходит некоторое разделение. Если мы проверим их, мы увидим, что компоненты L2
все еще хранятся в L1
.
L1 <- list(1:2, 3:4, 5:6)
L2 <- L1[-2]
object_size(L1)
## 248 B
object_size(L2)
## 176 B
object_size(L1, L2)
## 312 B
inspect(L1)
## <VECSXP 0x88622a8>
## <INTSXP 0x90ba950>
## <INTSXP 0x90ba870>
## <INTSXP 0x90ba790>
inspect(L2)
## <VECSXP 0x971dbf8>
## <INTSXP 0x90ba950>
## <INTSXP 0x90ba790>
Если Вы - планирование использования исключительно вектора, можно хотеть переключиться назад на индексируемый цикл, так как это передает намерение более ясно, чем цикл итератора. Однако, если эволюция Вашей программы в будущем может привести к изменению контейнера, необходимо придерживаться станд. использования и итераторы:: расстояние, которое, как гарантируют, будет работать со всеми стандартными итераторами.
Используя станд.:: расстояние более универсально, так как оно работает на все итераторы, не только итераторы произвольного доступа. И это должно быть настолько же быстро как Это - vec.begin () в случае итераторов произвольного доступа.
Это - vec.begin () является в основном адресная арифметика с указателями.
std::distance(vec.begin(), it)
даст Вам индекс it
указывает на, предполагая, что это указывает в vec
.
Carl
Вернитесь к индексируемому циклу.
В основном в 90% случаев, итераторы выше, это - один из тех 10%. При помощи итератора Вы делаете код более сложным и поэтому более твердым понять, когда вся причина использования итератора во-первых состояла в том, чтобы упростить Ваш код.
Вы пропускаете одно решение: сохраните индекс в случае, если Вы нуждаетесь в нем, но не используете его в качестве условия цикла. Работы над списками также и затраты (на цикл) являются O (n) и дополнительный регистр.
Я всегда склонялся бы к хранению с итераторами по будущим причинам разработки.
В вышеупомянутом примере, если Вы, возможно, решили выгрузить станд.:: вектор для станд.:: набор (возможно, Вам был нужен уникальный набор элементов), с помощью итераторов, и расстояние () продолжит работать.
Я вполне уверенный, что любые проблемы производительности были бы оптимизированы на грани его являющийся незначительным.
Для векторов я всегда использую целочисленный метод. Каждый индекс в вектор является той же скоростью как поиск массива. Если я собираюсь быть использованием значения много, я создаю ссылку на него для удобства.
векторные итераторы могут быть немного быстрее, чем индекс в теории, так как они используют адресную арифметику с указателями для итерации через список. Однако обычно я нахожу, что удобочитаемость стоит минимального различия во время выполнения.
Я использую итераторы для других контейнерных типов, и иногда когда Вам не нужна переменная цикла. Но если Вам нужна переменная цикла, Вы не делаете ничего кроме создания Вашего цикла тяжелее для ввода. (Я не могу ожидать автоматического 0x C++..)