Is there any reason not to send a parameter as a const &
, instead of by value, when it will not be changed and no copy will be made? My understanding is that a const
by value parameter is the same as without the const
(and won't overload each other) so it will still be copied.
I know it's best for large objects to send by const &
, but I don't know where the line for this is. Or if even small parameters should be sent by value if they won't be changed or copied.
Note:: I tried searching for this but the topic is fairly vague so I did not find any good answers, I apologize if this has been answered already (found many questions about when to use const
when to use const &
but not about the advantages of value vs const &
for objects not obviously large).
The important difference is that when passing by const reference, no new object is created. In the function body, the parameter is effectively an alias for the object passed in. Because the reference is a const reference the function body cannot directly change the value of that object.
Passing a parameter by const reference should be chosen where the semantics of references are actually required, or as a performance improvement only if the cost of potential aliasing would be outweighed by the expense of copying the parameter. At times, copying your parameters can also give you locality benefits.
Pass Using Const Reference in C++ Now, we can use the const reference when we do not want any memory waste and do not change the variable's value. The above code will throw a compile error as num = num +10 is passed as a const reference.
When you pass by const reference, you take the argument in by reference (avoiding making any copies of it), but cannot make any changes to the original object (much as would happen when you would take the parameters in by value).
There's generally nothing wrong with passing read-only arguments as const-references, and for any sort of heavy-weight class that's surely the most efficient way to do it.
You might want to consider passing primitive types by copy, though, because there making the reference might actually incur more cost than just copying (e.g. copying would just fit into one register, while a reference might be implemented with a pointer, etc.).
Also, you can probably pass std::shared_ptr
and iterators by value, they're made for that.
As for passing by const-value, that's an implementation detail. Use it like this:
// Declaration:
int foo(int n, double d); // No "const"! Constness is not part of the interface.
// Definition
int foo(int n, const double d) // implementation detail
{
while (n--) { if (d > n) return n; }
}
In the implementation, you may or may not choose to use the argument variables directly and modify them (like n
), or you may choose to treat them as read-only (like d
), and you declare the arguments appropriately.
As a rule of thumb, you should pass primitive types such as pointers, int
, bool
, float
, double
by (non-const) value, and object types such as std::string
, std::vector
and custom classes by (const) reference. As an exception to this rule, there are light-weight classes that are specifically designed to be passed by value, such as smart pointers.
Passing a value by const value, e.g. void foo(const double bar)
, makes no sense -- why shouldn't foo
be allowed to modify its copy of bar
? Declaring the parameter as const has no use here.
Passing primitives by reference makes little sense as well. Behind the scenes, when a parameter is passed by reference, a pointer is passed by value. Copying a pointer is usually just as expensive as copying a primitive type (such as int
), and parameters of type const int&
look pretty weird to most C++ programmers.
Unless an interface demands it, primitives should be passed by value. Otherwise, const& is a better practice.
boost::is_fundamental
Identifying primitive types in templates
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With