So I was all set to bash include/data-swap.c for allocating on the heap every time you need to swap memory. Turns out that gcc can optimize out that temporary, and it ends up the same as std::swap.
But if we use operator new/delete instead of std::malloc the optimization doesn't take place: https://godbolt.org/z/vtxqD2