Search code examples
c++classconstructoroperator-overloadinginitializer-list

Why does the textbook uses an initializer list as the return value of operator-(complex a)?


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);?


Solution

  • 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 }.