The only "danger" in passing a temporary as const&
happens if the function creates an object that survive the function call itself that stores in itself a const&
.
Think to
class A
{
const string& a;
public:
A(const string& a) :a(a) {}
void act() { .... /* use a */ }
};
A* foo(const string& s)
{ return new A(s); }
int main()
{
A* pa = foo(string());
//here, pa->act() will act on a dangling reference.
}
If your foo
function just use the string, but doesn't retain references for later use, passing a temporary is perfectly safe.
If this happens using a "boot function" or a default temporary value makes no difference for the resulting code.
At that point using one or two function is much more a matter of style and opportunity: how many chances are for the two functions to differentiate during further development?
If the answer is "none: the second function is just THE definition (or a shortcut) for a very frequent case" than default value does perfectly the job.
If the answer is "let's fall back to the other function BY NOW, and later be more specific" then two function are preferrable.
Default values, are however NOT the chance in case the function are templates, and you want type deduction to work:
template<class C, class T>
void fn(int i, basic_string<C,T>& s = ????);
you cannot use std::string() since it wont work for C
other than char
, and cannot use std::basic_string<C,T>()
since it will not allow to deduce, upon a fn(5)
call to know what C and T should be.
So you will end-up with
void fn(int i) { fn(i,string()); }
.