It shows us why just using C/C++ is not a performance-wise decision. You need to spend more time developing the product and spend MORE time to improve it's performance.
See "Useless use of cat awards" from days of yore: http://partmaps.org/era/unix/award.html#uucaletter
cat(1) almost certainly internally buffers data (32KB here) thus context switches occurs. Shell creates pipe which is buffered inside kernel.
All of this muffles measurements.
What was one or several read(2) calls + processing is now one or several calls of maybe smaller sizes + whatever scheduling differences + in one of the examples OP used /usr/bin/time of the whole thing also.
This is of course is not visible because data were dumbed down by using time() which has horrible granularity, but when finer grained timer it'd be visible, I'm sure.