4

I am unsure about how function calls are translated and I am afraid that passed variables are copied into local variables when they don't need to be. I could avoid unnecessary copying by using global variables, but that cannot be a good solution...

1) When variables are not changed in the target function, would it be better to pass them as pointers, references, or const?

void fkt1(int i, int j){
  do_something();
  printf("%d", i+j);
}

int main(){
  int i = 5;
  int j = 6;
  fkt1(i, j);
}

2) Is it expensive to pass variables to a function when they are not used within it. E.g., to keep a common interface, such as:

template <typename T>
void fkt2(T a, T b, int len = -1){ 
  do_something();
  printf("%d", a+b);
}

template<>
void fkt2<char*>(char* a, char* b, int len){
  do_something();
  strcpy(a+len, b);
  printf("%s", a);
}

or

class base{
public:
  virtual bool calc(int i, int j, int k, int l) = 0;
  base *next1;
  base *next2;
}

class derived1 : public base{
public:
  bool calc(int i, int j, int k, int l){
    return (next1->calc(int i, int j, int k, int l) || 
            next2->calc(int i, int j, int k, int l))
  }
}    

class derived2 : public base{
public:
  bool calc(int i, int j, int k, int l){
    return (return i+j > 5)
  }
}    

class derived3 : public base{
public:
  bool calc(int i, int j, int k, int l){
    return (return j*k < l)
  }
}    

Comments are much appreciated.

u17
  • 2,776
  • 4
  • 31
  • 43
  • Is this on x86? Do you care about supporting more than 1 architecture? Some architectures pass more arguments than others in registers. – nmichaels Jul 29 '10 at 15:01
  • At this point, I only care about x86 – u17 Jul 29 '10 at 15:27
  • How time critical is your code? If you are timing down to the nano second to pricisely let a hydrogen atom into the plasma stream of the LHC then this may be an appropriate question. Otherwise thinking about this cost is just pointless. There are so many other things that are slowing your processes down by much larger amounts that the difference will not even be measurable. So write the code so that it is easy to read and understand. – Martin York Jul 29 '10 at 17:16
  • It is time critical, I measure its performance in ms. If you add up enough ns, you'll end up with ms. Consider a loop with 1MM iterations... :) – u17 Jul 29 '10 at 18:35

5 Answers5

17

Don't worry about the performance issues at this point.

Focus on the algorithmic cost of your function, not the trivial things: guessing performance issues is a bad idea.

If you really encounter performance issues and have maintainable code, it will still be time to improve it.

Now to really answer the question:

You may pass const references when the object you have to pass really shouldn't be copied. If you have to pass integers, or simple structs (aka. small types), using a const reference or even a pointer is probably too much work: you will clutter the code with uneeded complexity were the compiler would probably have optimized things anyway.

ereOn
  • 53,676
  • 39
  • 161
  • 238
  • 2
    Not to mention, passing a pointer is no less work than passing an integer of the same size! – caf Jul 30 '10 at 08:37
4

See this answer for how to pass objects to functions in C++.

Otherwise I fully agree with ereOn. First write correct, simple, and easy-to-maintain code, and limit performance consideration to application design and algorithms. If you later find you have a performance problem, measure first, then try to improve, then measure again.

Community
  • 1
  • 1
sbi
  • 219,715
  • 46
  • 258
  • 445
2

If you're dealing with complex types, like structs or classes, then it depends on the copy constructor. If it does a deep copy, then passing a copy is likely fairly expensive, and you should use a reference or pointer instead. Even if you only do a shallow copy, there might be a small performance benefit from using a reference, but it's minimal at best.

In general, it just doesn't matter; what matters is what is done in the function, and the cost of passing parameters one way or another is neglible. Passing parameters as a copy, a pointer or a reference should depend on what you need to do with that parameter, not which is faster.

Michael Madsen
  • 54,231
  • 8
  • 72
  • 83
2

Global variables may actually hurt performance due to cache locality. But you should avoid them just for being global variables, performance notwithstanding.

1) If variables are not changed in a function then pass them as const references in C++. In C just pass by value so the original argument can't be changed. This is for good programming practice, not performance.

2) Passing an unused variable will still require the call stack to be built with it included. However, many processors have calling conventions that just pass parameters in registers. Let the compiler do the optimization; it's good at it.

The performance issues you're pondering are trivial given today's processor speeds and compiler capabilities. Don't design your code with parameter constraints based on performance fears. It will only degrade the quality of your design.

Amardeep AC9MF
  • 18,464
  • 5
  • 40
  • 50
0

Function calls (including parameter passing) nowadays comes with relatively little cost. This cost is e.g neglectable if you have any other complicated task such as printf or so in your function.

To get the best, you could try to hold your functions definitions in include files and flag them with inline. This is supported in C++ and C99 and should do the best possible in most common circumstances.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • Except that inlining sometimes makes gargantuan functions that won't fit in cache, thus becoming a pessimization. It's all about measurement. – nmichaels Jul 29 '10 at 15:03
  • @Nathon: Except that's out of the programmers control. You have to use implementation-specific extensions to tell a compiler *not* to inline functions, and of course the only smart way to know which functions to do that to is after profiling and looking at the assembly. – GManNickG Jul 29 '10 at 19:48