As answered in this question by Charles Bailey pass by constant reference should be considered when the object type is large but what kind of object is considered large?
EDIT: OK for providing more data that could be used to provide a more concrete answer I decided to add a real world problem to this description.
Suppose we have an object like this:
typedef struct dipl {
quint16 __id;
quint16 __pos;
quint16 __len;
} data;
And we have another object like this:
class bidipl
{
public:
bidipl();
quint8 id();
void setid(quint8 __id);
void appenddipl(dipl __dipl);
private:
qint8 _M_id;
dipllist _M_dipllist;
};
Where dipllist
is typedef QList<dipl> dipllist;
. Objects dipl
and bidipl
are created once but accessed over maybe 100 times a minute. So how should we pass dipl
to our append function?
void appenddipl(dipl __dipl);
Or
void appenddipl(const dipl& __dipl);
What should be considered large enough to justify passing by reference instead of by-value? You will find answers varying from:
std::pair<int, int>
should be passed by reference.to
vectors
,strings
)My personal taste is: primitive data by value, structures by reference.
The only productive answer you will find by profiling the specific application on the specific architecture. Any talk about performance without actual profiling is in vain.
Anything that is not a fundamental type, meaning any class object, struct, or container
As Charles said, when the value in question has a size equal to or smaller than the size of a reference to the object, there is an obvious performance gain for just passing the value instead of a reference. However, since accessing the value MAY require a dereference operation, depending on details about the context and how "smart" the compiler is, it could still possibly be "worth it" to pass around a value whose size is slightly larger than a reference. However, that is starting to split hairs and is rarely significant.
There are two separate costs associated with passing objects by value: Copying the data representation, and executing constructors. You need to consider the cost of both.
Copying data is generally fast, but keep it within reason. It's OK to pass
struct { int[7]; }
by value, but probably not so much forstruct { int[20000]; }
.Executing constructors may perform dynamic allocation, which brings the risk of exceptions and the cost of synchronization. This may be negligible, or it may be important. It depends.
The only variables you should probably pass by value unconditionally are those of word-sized, built-in types. For everything else you should think about the trade-offs.