There are multiple answers based on what you are doing with the string.
1) Using the string as an id (will not be modified). Passing it in by const reference is probably the best idea here: (std::string const&)
2) Modifying the string but not wanting the caller to see that change. Passing it in by value is preferable: (std::string)
3) Modifying the string but wanting the caller to see that change. Passing it in by reference is preferable: (std::string &)
4) Sending the string into the function and the caller of the function will never use the string again. Using move semantics might be an option (std::string &&)
I believe the normal answer is that it should be passed by value if you need to make a copy of it in your function. Pass it by const reference otherwise.
"For lvalue argument, ‘f1’ has one extra copy to pass the argument because it is by-value, while ‘f2’ has one extra copy to call push_back. So no difference; for rvalue argument, the compiler has to create a temporary ‘String(L“”)’ and pass the temporary to ‘f1’ or ‘f2’ anyway. Because ‘f2’ can take advantage of move ctor when the argument is a temporary (which is an rvalue), the costs to pass the argument are the same now for ‘f1’ and ‘f2’."
Continuing:
"
This means in C++11 we can get better performance by using pass-by-value approach when:
The parameter type supports move semantics - All standard library components do in C++11
The cost of move constructor is much cheaper than the copy constructor
(both the time and stack usage).
Inside the function, the parameter type will be passed to another function or operation
which supports both copy and move.
It is common to pass a temporary as the argument - You can organize you code to do this more.
"
OTOH, for C++98 it is best to pass by reference - less data gets copied around. Passing const or non const depend of whether you need to change the argument or not.