Michael
Michael

Reputation: 1058

Is using pointers and references of an object as function arguments lighter?

I was wondering if:

//Let's say T is a big class with + operand implemented.
T add(T* one, T* two)
{
     return *one + *two;
}

and:

T add(T& one, T& two)
{
    return one + two;
}

is lighter than this:

T add (T one, T two)
{
     return one +two;
}

If not, then why would someone use pointers or references to an object instead of the objects themselves as function's arguments if nothing will change the object's data?

Upvotes: 1

Views: 143

Answers (5)

Columbo
Columbo

Reputation: 61009

For light types, i.e. ones that fit into a register such as int, it doesn't make a difference as they are just as easy to copy as a pointer to them. Actually the additional indirection might harm the performance instead, which is why you should avoid introducing it if not needed.
However, the types used could be expensive to copy. An every day example is std::string. References avoids copies and are favoured wherever a function requires "heavy" objects.

In function templates one should generally use references when taking various object types, unless you are certain that the only types involved are "light", such as iterators or scalars.
There are less obvious exceptions to this rule though. Consider std::accumulate:

template< class InputIt, class T >
T accumulate( InputIt first, InputIt last, T init );

Here, init is taken by value. The reason is rather simple: In usual implementations init is modified as it is directly used inside the computations - no intermediate object is introduced.

template<class InputIt, class T>
T accumulate(InputIt first, InputIt last, T init)
{
    for (; first != last; ++first) {
        init = init + *first; // Here
    }
    return init;
}

Pointers should per se not be used for indirect function parameters. They are used in C, where references don't exist.

Upvotes: 4

Jonathan Wood
Jonathan Wood

Reputation: 67345

No, your last version is "lighter".

But that's because int arguments can easily be passed on the stack. For larger data types, classes, etc., passing pointers is more efficient.

Also, if you needed to change the value of one of the arguments inside your function, you would need a pointer (of which references are a type of) to it in order to modify it.

Upvotes: 1

Jeremy Friesner
Jeremy Friesner

Reputation: 73304

If by "lighter" you mean "more efficient", the answer (for ints) is no -- the only time passing argument by pointer or by reference might be more efficient that passing by value is if the object you are passing is very large (e.g. sizeof(theObjectType) is significantly larger than the 4 or 8 bytes which is the typical size of a pointer), or if the object's class has a copy constructor whose implementation is computationally expensive. Note that when passing by pointer or by reference, the CPU has to dereference the pointer/reference when accessing the data, which isn't entirely cost-free.

If not, then why would someone use pointers or references to an object instead of the objects themselves as function's arguments if nothing will change the object's data?

It could be that they want to communicate to the function a specific instance of the object rather than (only) the contents of the object. For example, it's possible (although bad practice) to write a function that behaves differently if you passed in a pointer-to-a-particular-global-object than it would behave if passed in any other pointer.

Passing by pointer also gives the caller the option of passing in NULL as an argument, which can be useful if you want the caller to be able to specify "no value has been provided for this argument".

Upvotes: 3

Deduplicator
Deduplicator

Reputation: 45704

The answer, as so often, is: It depends.

If you want to know whether copying or passing by reference is cheaper, or the right thing, consider these:

  1. How expensive is copying the object, compared to a pointer to it.
    Anyway, depending on how the argument gets passed, sometimes the copy can be omitted.

    For an int, the pointer/reference is at best no more expensive.

  2. Remember there are benefits to reduced aliasing.
  3. Remember that you can always pillage arguments passed by value ruthlessly, just like those passed by rvalue-reference.
    Not so for others.

    Not that those considerations are of consequence for int, or other types not managing more expensive resources.

  4. Does it make sense to omit the argument completely?
    In that case, you have to pass by pointer, or use something like the future std::optional.
    If not, pointers are the semantically wrong choice.

Anyway, never pass by non-const pointer or reference, unless it should be modified by the function.

Also, if you are serious about performance, always measure.
And remember that most of the time is spent in only a small part of your code.

Upvotes: 1

vmcloud
vmcloud

Reputation: 652

When using primitive type, pass by pointer or reference it is not lighter than pass by value. But if it is a large object, pass by pointer or reference will be lighter than pass by value, because of the overhead in copying large object.

Upvotes: 4

Related Questions