Short answer
On Windows, compiling with Visual Studio 2010 in release mode, oriented to the x64 platform, passing expanded arguments is much slower than passing a single structure by reference or even by value.
Results:
Multi result = 0; multi iterations = 10000 Ref result = 0; ref iterations = 10000 Value result = 0; value iterations = 10000 --------------------------------------------------- Timer "multi args": Total time = 0.387886 ------------------------------------------ Timer "struct by reference": Total time = 0.0679177 ------------------------------------------ Timer "struct by value": Total time = 0.143382
Observation
The more your function performs the calculations in its body, the less the overhead of copying harms the work. In fact, I compared a function that only performs a few add-ons and one unit.
Some details now
I defined a structure containing all your parameters
struct Args{ int leftchild; int rightchild; int ly_index; int uy_index; int bit; int nodepos; int amount; int level; Args(int l, int r, int ly, int uy, int b, int n, int a, int lev) : leftchild(l) , rightchild(r) , ly_index(ly) , uy_index(uy) , bit(b) , nodepos(n) , amount(a) , level(lev) {} };
and 3 functions.
static size_t counter1 = 0; static size_t counter2 = 0; static size_t counter3 = 0; int FindPoints(int leftchild, int rightchild, int ly_index, int uy_index, int bit, int nodepos, int amount, int level) { ++counter1; leftchild = leftchild + (rightchild + ly_index + uy_index + bit + nodepos + amount + level) / 100 - 1; return leftchild ? FindPoints( leftchild, rightchild, ly_index, uy_index, bit, nodepos, amount, level) : 0; } int FindPointsRef( Args& a ) { ++counter2; a.leftchild = a.leftchild + (a.rightchild + a.ly_index + a.uy_index + a.bit + a.nodepos + a.amount + a.level) / 100 - 1; return a.leftchild ? FindPointsRef( a ) : 0; } int FindPointsValue( Args a ) { ++counter3; a.leftchild = a.leftchild + (a.rightchild + a.ly_index + a.uy_index + a.bit + a.nodepos + a.amount + a.level) / 100 - 1; return a.leftchild ? FindPointsValue( a ) : 0; }
They all perform the same task, but first take the arguments , as in your question , the second takes the structure of the arguments by reference , and the third takes a struct by value .
I built the program using Visual Studio 2010, released the x64 configuration, and I measured it using the home class, which simply terminates the Windows QueryPerformanceCounter function and provides a convenient output statement.
The main function looks like this:
int main() { // define my timers PersistentTimer timer_multi("multi args"); PersistentTimer timer_ref("struct by reference"); PersistentTimer timer_value("struct by value"); int leftchild = 10000; // number of iterations; 10000 to prevent stack overflow int rightchild = 1; // sum of other values is < 100 (look to FindPoints* implementations) int ly_index = 2; int uy_index = 3; int bit = 4; int nodepos = 5; int amount = 6; int level = 7; // define structs of arguments for second and third function Args args_ref( leftchild, rightchild, ly_index, uy_index, bit, nodepos, amount, level ); Args args_copy( leftchild, rightchild, ly_index, uy_index, bit, nodepos, amount, level ); // return values initialized to a non zero value just to be sure that functions have done thir job int a1 = 5; timer_multi.measure([&]{ a1 = FindPoints( leftchild, rightchild, ly_index, uy_index, bit, nodepos, amount, level ); }); std::cout << "Multi result = " << a1 << "; multi iterations = " << counter1 << '\n'; int a2 = 5; timer_ref.measure([&]{ a2 = FindPointsRef( args_ref ); }); std::cout << "Ref result = " << a2 << "; ref iterations = " << counter2 << '\n'; int a3 = 5; timer_value.measure([&]{ a3 = FindPointsValue( args_copy ); }); std::cout << "Value result = " << a3 << "; value iterations = " << counter3 << '\n'; // print timer results std::cout << timer_multi << timer_ref << timer_value; getchar(); }