If I have a function like void func(size_t x)
and I call the function func(5)
, is 5 immediately converted to size_t
type? Does this hold generally for all types?
I ask because I swear I've seen people write code where they do stuff like func(5.0)
(passing 5 as a double) or func(0UL)
(passing 0 as an unsigned long int). Is this really necessary? Can't we just pass in whatever we want, and C++ will treat it as the type that I used to define the function?
To make a decision whether to use pass by reference or pass by value, there are two simple general rules: If a function should return a single value: use pass by value. If a function should return two or more distinct values: use pass by reference.
The call by reference method of passing arguments to a function copies the reference of an argument into the formal parameter. Inside the function, the reference is used to access the actual argument used in the call. This means that changes made to the parameter affect the passed argument.
If you're calling a function that needs to take a large object as a parameter, pass it by const reference to avoid making an unnecessary copy of that object and taking a large efficiency hit. If you're writing a copy or move constructor which by definition must take a reference, use pass by reference.
#include <iostream> #include <set> using namespace std; void foo(set<foobar>); For "small" types (e.g., char , short , int ) you generally want to pass by value. For something that's (potentially) as large as a set<whatever> passing by ( const ) reference is generally preferred.
If there is an implicit conversion between the argument type and the type passed to the function then the argument will be converted. If there isn't one, like trying to pass a std::list
to a function that expects a std::vector
then it won't and you will get an error.
One reason to use a specific literal, like func(5.0)
or func(5UL)
is if func
is a template function, or is overloaded. If func
is a template or is overloaded (for the appropriate types) then func(5.0)
, func(5UL)
and func(5)
would generate/call 3 different functions. One for a double
, one for a unsigned long
and one for an int
. This could be meaningful as there could be specializations/overloads handling these types differently.
You also run into cases like std::accumulate
whose third parameter, the accumulator, has its own template type. Lets say you want to sum all of the elements in a std::vector<double>
. If you use
std::accumulate(vector.begin(), vector.end(), 0)
then you would get a different result than
std::accumulate(vector.begin(), vector.end(), 0.0)
because the first call uses an int
to store the sum which will truncate each time, while the latter uses a double
and you will get the expected result.
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