"Zero cost abstraction" is a big fantasy. C++ is the king of hidden control flow and the costs are everywhere.
"Zero cost abstraction" is a big fantasy. C++ is the king of hidden control flow and the costs are everywhere.
If the target code is full of virtual function calls, yeah it gets gross. But if you need dynamic dispatch, C isn't going to be any better, you'll just be reinventing vtables by hand. Similarly, resource acquisition and release happens in C too, you just have to do it by hand instead of letting the destructor do it for you.
One ultra gross thing I see all the time in C++ disassembly though: constantly creating copies of a std::string, using them once for a comparison or something trivial, and then throwing them away. Multiple times in the same function. Its the developers fault, they shouldn't be creating new objects, they should be passing a pointer or a string_view or something. Unfortunately, C++ is copy rather than move by default, so its too easy to do this by accident.
Another gross thing? (Not C++ specific) 20 functions in a row that are just a single return instruction. Since functions have to have distinct addresses (that's my understanding at least) the compiler/linker can't easily fold identical functions together. Implementations can optimize as long as everything still works (the "as-if" rule). And I know some compilers do. But in practice, it seems they suck at it. So I get to look at 20 lines of assembly in a row that are just `bl`.
That tool is called Godbolt at gcc.godbolt.org. This is common enough that Godbolt is a verb with a lot of C++ programmers.