Think about [] for indexing an array vs .at(), vs direct array access
// direct
// multiply, memory fetch
base[index*sizeof(element)]
// function call, return
// multiply, memory fetch
element operator [](int index) {
offset index * sizeof(element);
return base[offset]
}
// function call, return
// comparison, branch, load, comparison, branch
// multiply, memory fetch
element at(int index) {
if (index > 0 and index < size) {
offset = base + index * sizeof(element);
return base[offset]
} else {
throw exception
}
}