C++ exceptions with modern compilers are zero cost (or very close to it) when not thrown. Exceptions can even improve performance by avoiding lots of checks and cache invalidations that checked error codes can cause.
They are more expensive when thrown.
Exceptions are the only way to return errors from constructors. Exceptions cannot be silently ignored. Exceptions make error handling obvious and easier to separate from function logic.
They are
not to be used for normal control flow. (3dsMax, I'm looking at you... whose bright idea was it to use C++ exceptions to implement "return" in your scripting language?)
The "basic exception safety" guarantee is trivial to provide, assuming you are following good C++ coding practices and RAII, and put a tiny bit of thought into your interfaces. The "strong" and "no throw" guarantees can be much harder (and sometimes impossible) to enforce, but that's ok, because 99% of the time you don't ever need to provide those. People who complain that certain algorithms and containers cannot be made "exception safe" don't always realize they can't be made error safe either for the exact same reasons. After all, exceptions are just automated error return values separated from the normal return value.
People also tend to forget that not catching an exception is also perfectly acceptable. If you can't handle the exception,
don't. If an exception happened, you only need to handle exceptions if you can somehow still fulfill your contract in the face of the particular exception - otherwise let the C++ language and RAII handle cleanup and get out of the way so someone else can handle it.
On the flipside there are the following concerns: Most game engines and code are not designed to be exception safe and do not properly use RAII and similar C++ mechanisms and so adding exceptions to them becomes a minefield. It is non-trivial to figure out what exceptions a function call may throw, without good documentation (Java tries to avoid this by specifying exceptions in the function header, but that tends to make things even worse). This is especially true in C++ when operator overloading is in effect. It is also sometimes hard to figure out when throwing exceptions is the correct thing to do.
In short, there are upsides and downsides to exceptions, just like any other feature in any other language. They are not a silver bullet for error handling, but neither are error codes or asserts as others would have you believe. C++ supports multiple forms of reporting errors, all of which should be considered and evaluated.
Above all - take everything you read (even this post) with a grain of salt. If you are happy and used to using error codes, keep using them (but you may want to at least consider following basic exception safety coding styles as they help prevent other kinds of bugs like memory leaks and memory corruption). If you want to try exceptions, go for it! And, like everything else, use your profiler if you care about performance.
Additional information about exceptions from Stroustrup, the creator of C++.