Can I pass a default value to a reference for a std::string ?

Yes this is legal. const will ensure temporary be lasting till function doStuff finishes.

§ 12.2.5

A temporary bound to a reference parameter in a function call (5.2.2) persists until the completion of the full-expression containing the call.


Better will be

void doStuff( std::string const & s1, std::string const & s2 = std::string());

To avoid extra temporary const char *. (Your variant has 2 temporaries: a const char * and empty std::string).

Or, using user-defined literals (C++14):

void doStuff( std::string const & s1, std::string const & s2 = ""s);

That to understand the semantic it is better to split the original statemenet .

void doStuff( std::string const & s1, std::string const & s2="");

into two statements

void doStuff( std::string const & s1, std::string const & s2);
doStuff( SomeString, "" );

In the call of the function the second argument is implicitly converted to an object of type std::string:

s2 = std::string( "" );

So in fact in the body of the function you will have

std::string const &s2 = std::string( "" );

That is constant reference s2 will refer temporary object std::string( "" ).