I'm not sure how representative your example is, but your function looks fine, as long as you document that it modifies the passed-in object. It's the calling that is bogus. I don't see why you can't just write:
std::string text("this is a test");
erase_whitespace(text);
cout << test;
Which does exactly the same thing as what you would hope happens in your original code, i.e. make a std::string, strip its whitespace, and output it, while keeping the std::string object itself on the stack instead of in the heap, and minimizing copies. Of course, the std::string's real storage is still on the heap, but you get the benefit of C++ disposing of the thing when the function or block is done.
I don't see why you need to save that line of code when it translates into no actual compiled code savings.
Now if you really needed this to, say, get stuffed into an equation, the usual thing to do is something like what Skizz wrote above (which works in regular C++, not just Visual C):
std::string erase_whitespace (const string &input)
{
std::string output(input);
output.erase (...);
return output;
}
What's nice about this is that you can pass a const char* as the parameter, and C++ will automatically create a temporary std::string from it, since std::string has a constructor that takes a const char*. Also, this doesn't mess with the passed-in object. And as Skizz pointed out, optimizers like this kind of construct for return values.