В случае op_x и op_y копилятор, ИМХО, позволяет создать неконстантную ссылку на временный объект, который затем деструктируется. В совершенно аналогичном им op_z компилятор это не позволяет.
Выхлоп показывает, что с4 и с5 — это ссылки на мертвые объекты (т.е. объекты, у которых отработал деструктор)
#include <iostream>
using namespace std;
class C
{
public:
C(int i): i(i), s("live") { cout << "ctor: " << i << endl; }
C operator+(const C& c) { cout << "plus: " << i << "+" << c.i << endl; return C(i+c.i); }
C& operator+(int ii) { cout << "op_x: " << i << "+" << ii << endl; i += ii; return *this; }
C& op_y(int ii) { cout << "op_y: " << i << "+" << ii << endl; i += ii; return *this; }
friend C& op_z(C& that, int ii) {
cout << "op_z: " << that.i << "+" << ii << endl;
that.i += ii;
return that;
}
void info() const { cout << "info: " << i << " " << s << endl; }
~C() { s="dead"; cout << "dtor: " << i << endl; }
private:
int i;
const char* s;
};
int main()
{
C c1(1);
C c2(2);
const C& c3 = (c1+c2);
const C& c4 = (c1+c2)+1;
const C& c5 = (c1+c2).op_y(2);
c1.info();
c2.info();
c3.info();
c4.info();
c5.info();
#ifdef C6
const C& c6 = c3+3;
c6.info();
#endif
#ifdef C7
const C& c7 = op_z(c1+c2, 4);
c7.info();
#endif
return 0;
}
$ g++ -DC6 -Wall b.cxx
b.cxx: In function ‘int main()’:
b.cxx:35: error: passing ‘const C’ as ‘this’ argument of ‘C& C::operator+(int)’ discards qualifiers
$ g++ -DC7 -Wall b.cxx
b.cxx: In function ‘int main()’:
b.cxx:39: error: invalid initialization of non-const reference of type ‘C&’ from a temporary of type ‘C’
b.cxx:11: error: in passing argument 1 of ‘C& op_z(C&, int)’
$ g++ -Wall b.cxx
$ ./a.out
ctor: 1
ctor: 2
plus: 1+2
ctor: 3
plus: 1+2
ctor: 3
op_x: 3+1
dtor: 4
plus: 1+2
ctor: 3
op_y: 3+2
dtor: 5
info: 1 live
info: 2 live
info: 3 live
info: 4 dead
info: 5 dead
dtor: 3
dtor: 2
dtor: 1
$
**/