I understand that volatile informs the compiler that the value may be changed, but in order to accomplish this functionality, does the compiler need to introduc         
        
First of all, the C++ standards do not guarantee the memory barriers needed for properly ordering the read / writes that are non atomic. volatile variables are recommended for using with MMIO, signal handling, etc. On most implementations volatile is not useful for multi-threading and it's not generally recommended.
Regarding the implementation of volatile accesses, this is the compiler choice.
This article, describing gcc behavior shows that you cannot use a volatile object as a memory barrier to order a sequence of writes to volatile memory.
Regarding icc behavior I found this source telling also that volatile does not guarantee ordering memory accesses.
Microsoft VS2013 compiler has a different behavior. This documentation explains how volatile enforces Release / Acquire semantics and enables volatile objects to be used in locks / releases on multi-threaded applications.
Another aspect that needs to be taken into considerations is that the same compiler may have a different behavior wrt. to volatile depending on the targeted hardware architecture. This post regarding the MSVS 2013 compiler clearly states the specifics of compiling with volatile for ARM platforms.
So my answer to:
Does the C++ volatile keyword introduce a memory fence?
would be: Not guaranteed, probably not but some compilers might do it. You should not rely on the fact that it does.