There are two primary ways of accessing elements in a [std::vector](<http://en.cppreference.com/w/cpp/container/vector>)

Index-based access:

This can be done either with the subscript operator [[]](<http://en.cppreference.com/w/cpp/container/vector/operator_at>), or the member function [at()](<http://en.cppreference.com/w/cpp/container/vector/at>).

Both return a reference to the element at the respective position in the std::vector (unless it’s a [vector<bool>](<http://stackoverflow.com/documentation/c%2B%2B/511/stdvector/2561/vectorbool-the-exception-to-many-many-rules#t=20160725190704070024>)), so that it can be read as well as modified (if the vector is not const).

[] and at() differ in that [] is not guaranteed to perform any bounds checking, while at() does. Accessing elements where index < 0 or index >= size is undefined behavior for [], while at() throws a [std::out_of_range](<http://en.cppreference.com/w/cpp/error/out_of_range>) exception.

Note: The examples below use C++11-style initialization for clarity, but the operators can be used with all versions (unless marked C++11).

std::vector<int> v{ 1, 2, 3 };

// using []
int a = v[1];    // a is 2
v[1] = 4;        // v now contains { 1, 4, 3 }

// using at()
int b = v.at(2); // b is 3
v.at(2) = 5;     // v now contains { 1, 4, 5 }
int c = v.at(3); // throws std::out_of_range exception

Because the at() method performs bounds checking and can throw exceptions, it is slower than []. This makes [] preferred code where the semantics of the operation guarantee that the index is in bounds. In any case, accesses to elements of vectors are done in constant time. That means accessing to the first element of the vector has the same cost (in time) of accessing the second element, the third element and so on.

For example, consider this loop

for (std::size_t i = 0; i < v.size(); ++i) {
    v[i] = 1;
}

Here we know that the index variable i is always in bounds, so it would be a waste of CPU cycles to check that i is in bounds for every call to operator[].

The [front()](<http://en.cppreference.com/w/cpp/container/vector/front>) and [back()](<http://en.cppreference.com/w/cpp/container/vector/back>) member functions allow easy reference access to the first and last element of the vector, respectively. These positions are frequently used, and the special accessors can be more readable than their alternatives using []:

std::vector<int> v{ 4, 5, 6 }; // In pre-C++11 this is more verbose

int a = v.front();   // a is 4, v.front() is equivalent to v[0]
v.front() = 3;       // v now contains {3, 5, 6}
int b = v.back();    // b is 6, v.back() is equivalent to v[v.size() - 1]
v.back() = 7;        // v now contains {3, 5, 7}

Note: It is undefined behavior to invoke front() or back() on an empty vector. You need to check that the container is not empty using the [empty()](<http://en.cppreference.com/w/cpp/container/vector/empty>) member function (which checks if the container is empty) before calling front() or back(). A simple example of the use of ‘empty()’ to test for an empty vector follows:

int main ()
{
  std::vector<int> v;
  int sum (0);

  for (int i=1;i<=10;i++) v.push_back(i);//create and initialize the vector

  while (!v.empty())//loop through until the vector tests to be empty
  {
     sum += v.back();//keep a running total
     v.pop_back();//pop out the element which removes it from the vector
  }

  std::cout << "total: " << sum << '\\n';//output the total to the user

  return 0;
}

The example above creates a vector with a sequence of numbers from 1 to 10. Then it pops the elements of the vector out until the vector is empty (using ‘empty()’) to prevent undefined behavior. Then the sum of the numbers in the vector is calculated and displayed to the user.

The [data()](<http://en.cppreference.com/w/cpp/container/vector/data>) method returns a pointer to the raw memory used by the std::vector to internally store its elements. This is most often used when passing the vector data to legacy code that expects a C-style array.

std::vector<int> v{ 1, 2, 3, 4 }; // v contains {1, 2, 3, 4}
int* p = v.data(); // p points to 1
*p = 4;            // v now contains {4, 2, 3, 4}
++p;               // p points to 2
*p = 3;            // v now contains {4, 3, 3, 4}
p[1] = 2;          // v now contains {4, 3, 2, 4}
*(p + 2) = 1;      // v now contains {4, 3, 2, 1}