Hadley Wickham — written Dec 15, 2012 — source
Iterators are used extensively in the STL: many functions either accept or
return iterators. They are the next step up from basic loops, abstracting
away the details of the underlying data structure. Iterators have three main
operators: they can be advanced with ++, dereferenced (to get the value
they refer to) with * and compared using ==. For example we could
write a simple sum function using iterators:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
double calculateSum(NumericVector x) {
double total = 0;
for(NumericVector::iterator it = x.begin(); it != x.end(); ++it) {
total += *it;
}
return total;
}Some differences to highlight about using iterators rather than contentional for loop indexing:
x.begin() and loop until we get to x.end().*it.NumericVector::iterator. Each
vector type has its own iterator type: LogicalVector::iterator,
CharacterVector::iterator etc.Iterators also allow us to use the C++ equivalents of the apply family of
functions. For example, we could again rewrite sum to use the
std::accumulate function, which takes an starting and ending iterator and
adds all the values in between. To use accumulate we need to include the
<numeric> header.
#include <numeric>
// [[Rcpp::export]]
double sum4(NumericVector x) {
return std::accumulate(x.begin(), x.end(), 0.0);
}The third argument to accumulate gives the initial value: it’s particularly important because this also determines the data type that accumulate uses (here we use 0.0 and not 0 so that accumulate uses a double, not an int.).
tags: stl
Tweet