The built-in array
int a[4] = {3, 1, 4, 1}; makes an array: four ints of one type, stored side by side in one block of memory. The 4 is its size. It is fixed when you compile, so the array can never grow or shrink.
Each element has an index: its position, counted from 0. a[0] is the first value, 3, and a[3] is the last, 1. An array of size 4 has the indexes 0, 1, 2 and 3. There is no a[4].
An int takes 4 bytes here, so the elements sit 4 bytes apart. a[i] is at the start of a plus i × 4 bytes. The computer works out that address in one step, so reaching any element is just as fast. No searching.
Using it
a[2] = 9; works out where element 2 is and stores 9 there. The 4 that was in it is gone. Only that one element changes; its neighbours stay as they were.
for (int x : a) visits every element in order. It knows where to stop because a's type, int[4], includes the size. Each value is copied into x and added to sum: 3 + 1 + 9 + 1 = 14.
Nothing stops you writing a[4]. C++ does not check the index while the program runs: a[4] just works out an address past the end, memory that is not part of a. That is undefined behaviour: anything may happen.
std::array
std::array<int, 4>, from <array>, holds the same four ints side by side, at no extra cost. But it behaves like a normal value: you can copy it with =, and it keeps its size when you pass it to a function.
Line 9 prints sum, 14. Line 10 prints b.size(), 4. The size is part of b's type, so b.size() is known when the program is compiled and costs nothing to ask for.
b[4] is just as unchecked as a[4]. But b.at(4) checks the index first. 4 is not below the size, 4, so it throws std::out_of_range, an error you can catch, and never touches memory past the end.
What happens
;; step 1/9 · declare
4 int a[4] = {3, 1, 4, 1};
int the type of every element
a the array's name
[4] the size: 4 elements, fixed at compile time
{...} the starting values, in order
memory one block, no gaps: 3 | 1 | 4 | 1
sizeof(int) is 4 bytes on every mainstream platform (the ILP32, LP64 and LLP64 data models used by Linux, macOS and Windows). The C++ standard only promises at least 16 bits, so check with sizeof if it matters. The figure marks byte offsets from the start of the array (+0, +4, +8, +12) rather than real addresses: the real address of a changes from run to run.