There is a difference how exceptions are technically handled between natively compiled languages such as C++ and languages using byte-code being executed on a virtual machine such as Java or C#.
C++ compilers usually generate code that protocols the information needed for exception handling at runtime. A dedicated data structure is used to remember entrance/exit of try blocks and the associated exception handler. When an exception occurs, an interrupt is generated and control is passed to the OS which in turn inspects the call stack and determines which exception handler to call.
Further details are pretty well explained in the following article by Vishal Kochhar:
How a C++ compiler implements exception handling
In Java or .NET there is no need for the overhead of maintaining exception handling information as the runtime will be able to introspect the byte code to find the relevant exception handler. As a consequence, only exceptions that are actually thrown are causing an overhead.