Первое возвращает по ссылке, второе по значению. Первое просто возвращает адрес, второе делает копию. Как определить, что нам нужно?
Где у нас результат: в локальной переменной или нет?
Перед нами операция «унарный плюс», которая, скорее всего, ничего не делает и return *this. Этот самый *this точно не локальный. Потому возвращаем по ссылке, String&.
А теперь возьмём бинарное сложение. Мы создаём новую строку (как локальную переменную, разумеется), заносим в неё сумму… а чтобы она не исчезла раньше, чем её подберёт вызывавшая подпрограмма, вернём по значению (String).
Для виртуальных функций обычно перестраховываются и возвращают по значению (String). Чхают на копирование, зато если вдруг потомку потребуется вернуть что-то локальное, он без проблем вернёт.
class Father {
private:
String fName;
public:
virtual String& name() const { return fName; } // пока всё нормально, но…
};
class Son : public Father {
public:
String& name() const
{ return Father::name() + "'s son"; } // ошибка, возвращаем локальную переменную!
};