A string is an opaque container holding a, possibly zero length, linear sequence of characters. Understanding the implications of this statement is the foundation for understanding all mozilla's string classes.
There are several reasonable ways to produce a string result from a function. If you are already holding the answer as a sharable string, you can simply return that string (pass-by-value). Otherwise, the most efficient and flexible way to return a string is to assign your result into a non-const reference parameter. Don't bother to create a sharable string from scratch with your generated result.
Why? The two things you want to minimize in string manipulation are, in order of importance, heap allocation, and moving characters around.
const PRUnichar* aKey;
printf("%s\n", NS_ConvertUCS2toUTF8(aKey).get()); // GOOD
// the simplest way to get a |printf|-able |const char*| out of a string
// works just as well with an formal wide string type...
const nsAString& aString = ...; // perhaps it's a parameter
printf("%s\n", NS_ConvertUCS2toUTF8(aString).get());
// But don't hold onto the pointer longer than the lifetime of the temporary!
const char* cstring = NS_ConvertUCS2toUTF8(aKey).get(); // BAD!
printf("%s\n", cstring); // |cstring| is dangling