I will write my point starting from another blog post of one Java enterprise solution provider. In short it states this: for medium/large programs Java is fast(er) than C/C++.
Before stating any comparison between any platforms, we must understand how works VM programs compared with compiled programs. C# and Java are programs that targets a VM (Virtual Machine) and C++ creates an executable. The main difference between those two is that the VM instructions are not the processor instructions, but are some abstract, independent codes. Those are smaller and easier to compile but they are not processor instructions.
In contrast how it is a C++ application made: a developer writes his code in C++ (or C), there is a compiler that understand what he/she writes, it creates an application that calls from operating system various functionality and for code that developer writes the CPU instructions. The compile time may take some time, like a full blown application like OpenOffice may take more than 10 hours on a 2GHz+ CPU.
How a Java/C# application is made: a compiler does simply translates in simple statements that are much higher level than instructions and makes a bytecode application. It is named .class or .jar in Java (Jar is a zip archive that contains more .class files) or .exe or .dll that contains MSIL code. At running time, a runtime, named JIT, for only functions that are called by your program will make the corresponding machine instructions. Also, a difference is that most JITs come with automatical memory management compared when C++ does not. There are still C++ garbage collectors still. The garbage collector have the big advantages of cache locality and really cheap allocation of small objects, but have the disadvantage of pauses when the automatically memory cleanup occurs.
Judging technologically, a JIT, should get better performance than a static compiler like C++. Some of the reasons are: it knows the target machine, so it can align data and rearange structs in memory, it can use paralel instructions that the host machine supports, just because only the used code is translated in instructions, for large frameworks will mean that it will get better cache locality, it can inline for specific cases functions that are in other libraries as they are bytecode instructions, not effective code. Also, the garbage collector should bring an almost cost-free allocation and better cache locality. The dynamic nature of JIT it gives for it equal or more informations than any static compiler may get.
In practice anyway, I must disagree that a Java/.NET virtual machine can bring the same performance on the same code than a C++. For a specific loop you may get similar performance but using the CPU tunning on new compilers, profile guided optiomizations (which gets dynamic information of how your application behaves and gets almost the same information that a JIT have), the ability to do custom made memory allocator (a common used one for embeded programming is named: circular buffer, which to allocate an item is as cheap as a garbage collector alloc, meaning an pointer add, but without the disadvantage of pauses that garbage collector gives), the bridge from outside world, meaning that the calls to a native operating system, are always made through a translating layer (named JNI or PInvoke) that imply some overhead as marshaling, C++ can be linked with other object files that can be optimized in assembly by CPU makers. Also, the long compiling time it also translates in a lot of more analisys that is done by static compilers to get the latest drop of performance.
The good side is that .NET or Java gives in their field just enough performance. Also, a well written algorithm can get much better performance regardless a language. Just by using Generics, you will get a big performance increase as there is no need for type checking (which means an overhead). Also, generic collections and LinQ will offer to you a good performance. The garbage collector does not guarantee to not have memory leaks, but guarantees to you to not have double deleted pointers or invalid pointers at all. When you access a pointer is either null or a data of the type you've specified. Where C#/.NET or Java are strong are mostly: integer operations, inlining function calls and constant propagation over a satelite/external assembies, the string operations, fast heap allocations, after startup they run enough fast that you will not notice that is an bytecode application.
The last thing that is important regarding speed: sometimes the speed is measured wrong. NaroCAD shows in profiling that it's abstraction layer is enough easy to work and the slowest thing is for now not the JIT or the runtime, but the C++/OpenCascade code. Not because OpenCascade is slow, but because OpenCascade as C++ code did not achieved yet as it has a complex codebase too much time to be optimized.
There is only one point I want it to make regarding speed. On a cheap laptop of those days you can make a clean build of NaroCAD that have more than 800 classes in 17 seconds and to build after a change in 3 seconds, that mostly imples to copy assemblies to a destination folder. At startup it loads all OpenCascade libraries, Windows dlls like UI ones make JIT for anything it needs like the component framework will take 10 seconds. From it, JIT is somelike 5-6 seconds to compile almost all NaroCAD, so as long as you will use more functionality, you will have over time around 2-3 seconds of extra jitt-ing, means a 0.1 delay on every operation only for the first time. If you don't want to wait for those 5 seconds and to improve dramatically the startup speed of NaroCAD, you can add a command like that using NGen: run cmd as administrator and from the folder of NaroCAD write: C:\Windows\Microsoft.NET\Framework\v2.0.50727\ngen.exe install narocad.exe