Hello

I must implement overloaded + (binary) operator. I have to use method like that: const Text & operator+(const Text &) const . Anyone knows how it may be done ? I know that I can't make new object in function and return it.

Ps: Class Text have pointer to char . It is used to create dynamic char table

Recommended Answers

All 9 Replies

Why can't you make a new object in the function and return it? Because you are returning const Text&?

That is the mistake, you can't implement operator+ returning a reference, it has to return an object so the prototype for your operator+ should be

const Text operator+(const Text &) const

and then you can create a new object and return it.

If you can lay your hands on More Effective C++ by Scott Meyers look up Item 20 which explains this in depth.

Hi thank you for replay . I know that it isn't good to return references to objects . I'm writing program for somebody who is studying at the university. This is his homework and I can't modify this method. I'm just wondering if it's possible to do.

It can be good to return references to objects when you can, for instance the return from operator+= can be a reference.

It is not possible to implement operator+ returning a reference and correctly handle memory.

It can be good to return references to objects when you can, for instance the return from operator+= can be a reference.

Maybe you meant, when overloading the = operator. It doesn't make sense to return a reference when overloading the += operator.

It is not possible to implement operator+ returning a reference and correctly handle memory.

Curious on why not.

I did not mean operator=, I surely would have said that if I meant it and in fact because of the nature of operator= and operator+= they would return the same type, both const references because the return the object that was assigned to.

You can't return a reference from operator+ because you are not returning either of the arguments but an complete different value, the result of adding the 2 arguments. That requires a new object that is created inside operator+.

This object could have 1 of 2 scopes, automatic (on the stack in most implementations) or allocated (on the heap in most implementations. Considering each case in turn for a generic type T

automatic variable (on the stack)

const T& operator+(const T& lhs, const T& rhs)
{
    T result;
    result = ... ; // Actual calculation of lhs + rhs however it applys to T
    return result;
}

The problem here is that result has automatic scope, as soon as operator+ returns it is destroyed. However you returned a reference to it not you have an invalid reference waiting to cause havoc in your program.

allocated variable (on the heap)

const T& operator+(const T& lhs, const T& rhs)
{
    T* result = new T;
    *result = ... ; // Actual calculation of lhs + rhs however it applys to T
    return *result;
}

OK now the result object exists beyond the lifetime of the call to operator+, the reference returned will be valid. However memory has been allocated, someone needs to delete that memory and that would be the calling function. This is not good, for instance consider the most basic use of operator+

T result, a, b;
... // Code to initialise a and b
result = a + b;

On line 3 operator+ is called and news a T on the heap and returns a reference to it. The calling code uses the assignment operator to copy from that returned reference into result, the reference is not stored anywhere so there is no longer and reference to the memory that was newed. You have a memory leak. You can not use this operator+ using the normal calling semantics for operator+ without leaking memory.

Neither of the 2 ways of allocating memory for the return value for operator+ works correctly when operator+ returns a reference. Therefore operator+ has to return an object then you can do this

const T operator+(const T& lhs, const T& rhs)
{
    T result;
    result = ... ; // Actual calculation of lhs + rhs however it applys to T
    return result;
}

Here we return an object so although result is destroyed when operator+ returns its value is copied into the returned object whose lifetime extends out into. What is returned to the calling code is an object with the right value, no memory is leaked anywhere and operator+ can be used with its normal calling semantics.


As a side note it is possible to write operator+ in such a way that the optimiser can perform a return value optimisation and cut out the extra object copy that occurs when returning an object. Additionally it is common practice if a object has operator+= and copy constructor to write operator+ in terms of operator+= which enables the posibility of return value optimisation, for any type T as

const T operator+(const T& lhs, const T& rhs)
{
    return (T(lhs) += rhs);
}

>>I did not mean operator=, I surely would have said that if I meant it and in fact because of the nature of operator= and operator+= they would return the same type, both const references because the return the object that was assigned to.

I'm sorry, Right now I see no good reason to return a constant reference for the += operator. It looks like it would obfuscate the code.
For example, If you return a constant reference for the += operator, then you are allowed to do this :

Foo f; //Foo(): val(0){}
Foo g = Foo(1); //Foo(int val);
Foo h = Foo(2);

cout << (F += g).getX();
cout << (((F += g)+=h)).getX();

It just looks like you are able to do more crazy code. So it would be nice if you can give some good reasoning to return a const reference for overloading the += operator.

And thanks for the other explanation. Didn't realize what you mean exactly by your first post.

For example, If you return a constant reference for the += operator, then you are allowed to do this :

Actually no, if operator+= returns const & then you can't do line 6 at all because the second += trys to modify the result of the first += which it can't because that value is constant.

Line 5 is only valid if getX is declared as const.

This is exactly the behaviour you want operator+= returns a value that can be used but not modified, or more simply it returns a value. The caller can copy the value if they choose into there own object and then modify it.

This is also exactly the semantics displayed by += when you use it with an int

int fi = 0;
    int gi = int(1);
    int hi = int(2);

    cout << (fi += gi) << endl;
    cout << (((fi += gi) += hi)) << endl;

I have just changed foo to int from you code. This compiles, even line 6. However line 6 in undefined behaviour and should be avoided, with the object line 6 wouldn't compile which is probably better than accidentally introducing undefined behaviour.

The reason for returning a reference in this and similar cases is that it is much more efficient than returning an object which entails object copying and possibly the creation of temporary nameless objects that have to be deleted again.

So the point is that by returning const reference, and the const is very important in this, from assignment operators you get a more efficient method that maintains the correct calling semantics.

P.S. and Off Topic

Count 1 Result: 1418854
Count 89 Result: 8581146

Hi thank you for replay . I know that it isn't good to return references to objects . I'm writing program for somebody who is studying at the university. This is his homework and I can't modify this method. I'm just wondering if it's possible to do.

Let me get this straight...

You're wasting your time doing someone else's college homework for them so that they can graduate with a degree and not know anything they're supposed to know. In addition, you're letting them take all the credit for your hard work done while they cavort around with the blonde down the hall?

Are you STUPID?!!?!??!?! Tell them to shove off and learn it themselves. If they graduate, that piece of paper will at least mean something then.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.