Functions with return values (C++)

2020-02-07 04:19发布

When main() calls a function which has a return value of some datatype ( primitive or user-defined ) , the statement in which the function is called is 'usually' an assignment .

Ex :-

class complex
{

private:

    int real;
    int imag;

public:

    complex();
    complex(int r,int i);
    complex operator + (complex c);
};

Suppose , the definition of my overloaded " + " is like this -

complex complex::operator + (complex c)
{
    this->real = this->real + c.real;
    this->imag = this->imag + c.imag;
    return *this;
}

I have my main function as follows -

int main()
{
    complex c1;
    complex c2(5,4);
    c1+c2;
}

In the main() above , consider the statement c1+c2 . The compiler treats it as c1.operator + (c2) . When this function is called by main , it returns a value to main() . What happens to this return value ??

标签: c++ function
6条回答
\"骚年 ilove
2楼-- · 2020-02-07 04:29

The value of the expression c1+c2 is ignored by your code, as you are not storing it anywhere. At most, the compiler will print some warning messages. To supress such warning messages, you could write :

(void)(c1+c2); //casting to void suppresses the warning messages!

See this:


The real issue with your code..

However, in your code, the implementation of operator+ is not semantically correct. To understand that consider this,

 int a=10;
 int b=5;

then, do you expect a+b to change the value of a? Should a become 15? No.

If you want that, then you would write a+=b instead. But in your code, c1+c2 behaves equivalent to the semantic of c1+=c2, as you're updating the value of this->real and this->imag in your implementation of operator+, which is not correct, semantically.

So the first fix is this:

complex complex::operator + (const complex& c) const
{                            
  complex result(c); //make a copy of c
  result.real += this->real; //add
  result.imag += this->imag; //add
  return result;
}

Now, this is semantically correct.

That said, there is still few things to be noted. When you write c1+c2, do you think the operation + is applied on either of the object? No. It doesn't apply on any of them, yet the member function operator+ gets invoked on c1 object which becomes this pointer inside the function. Why should it be invoked on c1 (or for that matter c2) if the operation doesn't apply on it?

This analysis makes it clear that operator+ shouldn't be a member function of the class. It should be a non-member function instead, and the signature then would be:

complex operator+(const complex &a, const complex &b);

But there is a small problem: in the computation of a+b, it needs to access to the private members of the class (real and imag are private members). So the solution is, operator+ should be implemented in terms of operator+=, and the latter should be added as a member function to the class, because the operation += in the expression a+=b does apply on a, as it modifies its value.

So here is my implementation of both operators:

class complex
{
  //...
  public:

    //member function
    complex& operator+=(const complex & c)
    {
          real += c.real; //same as: this->real+=c.real; this is implicit
          imag += c.imag; //same as: this->imag+=c.real; this is implicit
          return *this;
    }
};

//non-member function (its non-friend as well)
complex operator+(const complex &a, const complex &b)
{
    complex result(a); //make copy of a by invoking the copy-constructor
    result += b;  //invokes operator+
    return result;
}

Or you could join last two statements as:

complex operator+(const complex &a, const complex &b)
{
    complex result(a); //make copy of a by invoking the copy-constructor
    return result += b;  //invokes operator+, and then return updated 'result'
}

But there is another way to make copy. Why pass both arguments by reference? Passing the first argument by value would make the copy we need. So a better implementation would be this:

complex operator+(complex a, const complex &b)
{               //^^^^^^^^^ pass-by-value
    a += b; //a is a copy, after all - we can modify it!
    return a;
}

Hope that helps.

查看更多
劳资没心,怎么记你
3楼-- · 2020-02-07 04:29

The return value is discarded; as you are not storing it anywhere.

One important advice:

Ideally the definition for operator + should look like.

complex complex::operator + (const complex& c)
{                            ^^^^^^^^^^^^^^
  complex add; 
  add.real = this->real + c.real;
  add.imag = this->imag + c.imag;
  return add;
}

In your original code 2 copies of complex are made; among which at least 1 can be avoided with above format where the argument is pass by const reference.

Also, in your code you should not change the current object; (otherwise it becomes like operator +=()). So create a temporary inside the function and pass it by value.

查看更多
beautiful°
4楼-- · 2020-02-07 04:39

Another solution is to use operator + in global scope but as a friend of your class:

class complex
{
    // ...

public:

    // ...

    friend complex operator +(const complex &c1, const complex &c2)
    {
        complex c;
        c.real = c1.real + c2.real;
        c.imag = c1.imag + c2.imag;
        return c;
    }

    // ...

};

Using this technique you can also use an integer as argument (at the lhs) by adding:

    friend complex operator +(const int n, const complex &c)
    {
        complex c;
        c.real = n + c.real;
        c.imag = c.imag;
        return c;
    }

    friend complex operator +(const complex &c, const int n)
    {
        complex c;
        c.real = c.real + n;
        c.imag = c.imag;
        return c;
    }

So now you can also do

 complex c1, c2, c3;
 c3 = 1 + c2 + 8 + c1 + 2;

and your class is missing a (virtual) destructor, I would also make the member variables protected instead of private :)

查看更多
够拽才男人
5楼-- · 2020-02-07 04:44

It gets assigned into a temporal (invisible if you may) complex value. The lifetime of such value is until the expression that generated it ends, that's the ; at the end of c1+c2. So a new temporal object is created to store the result of the expression, and its destructed at the end of that line.

You shouldn't be modifying 'this' in your a + b operator, after evaluating a + b now a holds the result of the expression.

查看更多
时光不老,我们不散
6楼-- · 2020-02-07 04:44

In this case, it is silently dropped (but the sum is stored in c1 or c2). The compiler might (or might not) optimise the code by dropping the line entirely, because it doesn't do anything substantial. The resulting sum will be constructed and returned by the operator+, (a temporary variable will be created) and then destroyed immediately.

This happens in other cases, too. Consider this:

c2 += c1;

You can chain several additions like this together:

c4 += c3 += c2 += c1;

This is because operator+= also returns a value, but it is ignored like in your code.

By the way, I think you want to use operator+=.

查看更多
来,给爷笑一个
7楼-- · 2020-02-07 04:52

It's simply discarded, but AFAIK C++ will show error when a function expecting return value doesn't have return statement.

查看更多
登录 后发表回答