I am reading a textbook (of Bjarne Stroustrup) definition of class complex
class complex {
double re, im; // representation: two doubles
public:
complex(double r, double i) :re{r}, im{i} {} // construct complex from two scalars
complex(double r) :re{r}, im{0} {} // construct complex from one scalar
complex() :re{0}, im{0} {} // default complex: {0,0}
double real() const { return re; }
void ral(double d) { re = d; }
double imag() const { return im; }
void imag(double d) { im = d; }
complex& operator+=(complex z) { re+=z.re, im+=z.im; return *this; } // add to re and im
// and return the result
complex& operator-=(complex z) { re-=z.re, im-=z.im; return *this; }
complex& operator*=(complex); // defined out-of-class somewhere
complex& operator/=(complex); // defined out-of-class somewhere
};
The book also defines operations of complex:
complex operator+(complex a, complex b) { return a+=b; }
complex operator-(complex a, complex b) { return a-=b; }
complex operator-(complex a) { return {-a.real(), -a.imag()}; } // unary minus
complex operator*(complex a, complex b) { return a*=b; }
complex operator/(complex a, complex b) { return a/=b; }
I do not understand the third line above, which deals with unary minus. Why does it make sense to use an initializer list as the return value of operator-(complex a);
?
You have to have
return {-a.real(), -a.imag()};
because you want to return a complex
that is created from those two values. If you tried using
return -a.real(), -a.imag();
instead then you would return a complex
that was created from just -a.imag()
since the comma operator only returns the last value. Essentially, the code is exactly the same as
return -a.imag();
To make it more explicit, the author could have written
return complex{-a.real(), -a.imag()};
//or
return complex(-a.real(), -a.imag());
but that really isn't needed since the return value is always converted to the return type and with initializer lists, they are used like you had typed return_type{ initializers }
.