Know Your Sizes
Just because a type is complex, doesn’t mean it is expensive to copy.
I see code like this sometimes:
1void bar(const std::pair<int, int>&)
2{
3 // I avoided an extra copy!
4}
In a 64-bit machine, an std::pair
of integers is 64 bits. If you pass it to a function by reference, the compiler will pass in the address of the pair in a register, which is also 64 bits.
Instead of just putting the two integers in the register, you’re putting their address, so you have a useless indirection when you use the pair in the function!
1int foo( std::pair<int, int> p) { return p.first; }
2int bar(const std::pair<int, int>& p) { return p.first; }
1-_Z3fooSt4pairIiiE:
2+_Z3barRKSt4pairIiiE:
3 pushq %rbp
4 movq %rsp, %rbp
5 movq %rdi, -8(%rbp)
6- movl -8(%rbp), %eax
7+ movq -8(%rbp), %rax
8+ movl (%rax), %eax
9 popq %rbp
10 ret
Look at that line 8! What a silly dereference!
The entire pair fits in %rdi
, so just pass it directly. I’d go further: x64 has six registers available for parameter passing, which comes out to a total of 384 bits which are easily passed into the function before register spilling happens. For any arguments size fewer than 384 bits, just pass them in by value!
Tags: #C++ #programming