Applied C++: Return Multiple Values

One byte more and we have to use the stack.Still, we don’t need to load output param addresses, so it is faster than the output parameters method.Return Multiple Values Using an std::pairExample:auto pair_2() { return std::make_pair(31, 32); } // Just one line!// Use volatile pointers so compiler could not inline the functionauto (*volatile pair_2_ptr)() = pair_2;int main() { auto [p1, p2] = pair_2_ptr(); // Structured binding declaration printf("pair_2 p1 = %d, p2 = %d?.", p1, p2);}Disassembly:pair_2(): movabs rax, 0x200000001f # Just return 2 integers in rax retmain: # Note: simplified call [pair_2_ptr] # Just call the function mov rdx, rax # Use the values returned in rax shr rdx, 32 mov rcx, rax mov esi, ecx call printfPros:Just one line of code!No need to declare the local structure.Just like with the structures, returns up to 128 buts in registers, no stack is used.Cons:Pair is just two return values :(Just like with the structures, the function can’t be overloaded.Return Multiple Values Using an std::tupleExample:auto tuple_2() { return std::make_tuple(41, 42); } // Just one line!// Use volatile pointers so compiler could not inline the functionauto (*volatile tuple_2_ptr)() = tuple_2;int main() { auto [t1, t2] = tuple_2_ptr(); // Structured binding declaration printf("tuple_2 t1 = %d, t2 = %d..", t1, t2);}Disassemble:tuple_2(): movabs rax, 0x290000002a..# Good start, but..?.mov [rdi], rax # Indirect write to a output rax, rdi # Return the address of the parameter retmain: # Note: simplified mov rdi, rsp # Pass stack pointer as a parameter call [tuple_2_ptr] # Call the function mov edx, [rsp] # Get the values from the stack mov esi, [rsp + 4] call printfPros:The source code is one liner, just like with the std::pair.Unlike the std::pair, easy to add more values.Cons:Unfortunately, the disassembly is a mixed bag..We need to pass an address of the output tuple to the function, one per tuple.Even for two integers (64 bits), the return values are always on the stack..Slow :(What if we return more values in the tuple.Adding more values does not change the disassembly much: we still pass just one address pointing on the stack, then we put the values under that address (on stack), and then we load them back from the stack to use for printf().It’s slower than the pair and the structure, which both return up to 128 bits in the registers.But it’s faster than the output parameters, where we need to pass to the function few addresses, not just one.TakeawaysThe fastest methods to return multiple parameters in C++17 are by using local structure and std::pair.The std::pair must be preferred to return two values as the most convenient and fast method.Use output parameters when the function overload is needed.That’s why std::from_chars() uses output parameters and a return structure.Source code: Answer to “Do I Know This Already?” QuizThe std::pair is the most convenient and fast method to return two values.If we need to return more than two values, local structure (faster) or std::tuple (convenient) must be used instead.. More details

Leave a Reply