Dereference a pointer? That translates to a tiny fragment of machine code for "dereference pointer".
Create a lambda? That translates to a big blob of machine code for "set up this bunch of paperwork that will be used to painstakingly emulate a lambda".
Of course, it won't happen magically: someone has to go to the effort of defining the subset and building the compiler for it.
You can't expect the general-purpose compiler to automatically be as optimal as possible just because a program happens to use the subset. For example, the program might be being compiled into something like a java .class file meant for importing to a less conservative calling program. This would be incompatible with putting those bare metal optimizations in the .class file.
Interpreted languages such as Python or Ruby (or languages that run on a VM, like Java) go through an interpretation step _every time_ they are run that translates them down to machine language.
This gives compiled languages an inherent advantage in terms of runtime performance; programs written in these languages don't have the overhead of translating to machine code at runtime. This is typically why people advocate "next to bare metal" as having better performance.
In C and (sort of) C++ you can deal with actual bytes in actual memory locations. You can find the exact memory address of a data structure, and you can read or write directly to that location.
You can even prod the compiler to suggest that it uses real hardware registers for variables.
You can also control how memory is allocated and released.
In most languages an array is just an array. You usually don't care where it is in memory.
In functional languages you concentrate more on designing symbolic operations, and the fact that there's real memory under there somewhere is almost irrelevant.
But C/C++ are bare-metal-ish. In assembler you work directly with memory, but you can control program flow. You can jump/branch to any address in memory. Sometimes you can even overwrite your own code.
C/C++ won't let you do that.
As a former assembler guy, I find that C++ is the worst of both worlds. You get the cognitive overhead of dealing with memory management and pointer arithmetic and iterators, but the options for not working with them when you don't want to are limited - so it's hard to concentrate on the functional level, and you do a lot of the work the compiler/interpreter would usually do, but without the "do whatever you want" freedom of assembler.
With things like a JIT it can see it at runtime, but that's still overhead to handle the detection and the bail-out situations.
Edited: Correct my bad grammar.