Попробую рассказать об этом же более простыми словами.
Текст
String s3 = "Нас обманули, расходимся.";
означает вот что. Мы создаёт временную строку «Нас обманули, расходимся», а затем присваиваем её нашему s3. Конечно, компилятор это потом заоптимизирует, но это семантика языка, и ей надо следовать.
Есть два способа передать временный объект в функцию. Любую: хоть простую, хоть конструктор, хоть операцию =.
Первый — константная ссылка:
String(const String &S)
.
Второй способ из C++11 — временная ссылка:
String(String &&S)
.
Из-за этих временных объектов конструктор копирования и операция «присвоить», по-хорошему, должны брать const-ссылку. Вот вам аналогичный пример с операцией «присвоить».
class String
{
public:
String() {}
String& operator= (String& s) { return *this; }
};
String operator+ (String a, String b) { return String(); }
int main()
{
String s1;
String s2 = s1;
String s4;
s4 = s1 + s2;
}
Решается
String& operator= (const String& s)
.