Using STL Iterators

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:

  • We start at x.begin() and loop until we get to x.end().
  • Instead of indexing into x, we use the dereference operator to get its current value: *it.
  • Notice the type of the iterator: 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 

Related Articles