C++ FAQ Celebrating Twenty-One Years of the C++ FAQ!!!
(Click here for a personal note from Marshall Cline.)
Section 34:
[34.3] Is the storage for a std::vector<T> guaranteed to be contiguous?

Yes.

This means the following technique is safe:

#include <vector>
#include "Foo.h"  /* get class Foo */

// old-style code that wants an array
void f(Foo* array, unsigned numFoos);

void g()
{
  std::vector<Foo> v;
  ...
  f(v.empty() ? NULL : &v[0], v.size());   safe
}
The funny expression v.empty() ? NULL : &v[0] simply passes the NULL pointer if v is empty, otherwise passes a pointer to the first (zeroth) element of v. If you know a priori that v is not empty, you can change that to simply &v[0].

In general, it means you are guaranteed that &v[0] + n == &v[n], where v is a std::vector<T> and n is an integer in the range 0 .. v.size()-1.

However v.begin() is not guaranteed to be a T*, which means v.begin() is not guaranteed to be the same as &v[0]:

void g()
{
  std::vector<Foo> v;
  ...
  f(v.begin(), v.size());   Error!! Not Guaranteed!!
    ^^^^^^^^^-- cough, choke, gag; not guaranteed to be the same as &v[0]
}
Do NOT email me and tell me that v.begin() == &v[0] on your particular version of your particular compiler on your particular platform. I don't care, plus that would show that you've totally missed the point. The point is to help you know the kind of code that is guaranteed to work correctly on all standard-conforming implementations, not to study the vagaries of particular implementations.