views:

764

answers:

4

The sentence below is from, The Positive Legacy of C++ and Java by Bruce Eckel, about operator overloading in C++:

C++ has both stack allocation and heap allocation and you must overload your operators to handle all situations and not cause memory leaks. Difficult indeed.

I do not understand how operator overloading has anything to do with memory allocation. Can anyone please explain how they are correlated?

A: 

Operators are functions. Just because they add syntactic sugar does not mean you need not be careful with memory. You must manage memory as you would with any other member/global/friend function.

This is particularly important when you overload the when you implement a wrapper pointer class.

There is then string concatenation, by overloading the operator+ or operator+=. Take a look at the basic_string template for more information.

dirkgently
+3  A: 

I can imagine a couple possible interpretations:

First, in C++ new and delete are both actually operators; if you choose to provide custom allocation behavior for an object by overloading these operators, you must be very careful in doing so to ensure you don't introduce leaks.

Second, some types of objects require that you overload operator= to avoid memory management bugs. For example, if you have a reference counting smart pointer object (like the Boost shared_ptr), you must implement operator=, and you must be sure to do so correctly. Consider this broken example:

template <class T>
class RefCountedPtr {
public:
    RefCountedPtr(T *data) : mData(data) { mData->incrRefCount(); }
    ~RefCountedPtr() { mData->decrRefCount(); }
    RefCountedPtr<T>& operator=(const RefCountedPtr<T>& other) {
        mData = other.mData;
        return *this;
    }
    ...
protected:
    T *mData;
};

The operator= implementation here is broken because it doesn't manage the reference counts on mData and other.mData: it does not decrement the reference count on mData, leading to a leak; and it does not increment the reference count on other.mData, leading to a possible memory fault down the road because the object being pointed to could be deleted before all the actual references are gone.

Note that if you do not explicitly declare your own operator= for your classes, the compiler will provide a default implementation which has behavior identical to the implementation shown here -- that is, completely broken for this particular case.

So as the article says -- in some cases you must overload operators, and you must be careful to handle all situations correctly.

EDIT: Sorry, I didn't realize that the reference was an online article, rather than a book. Even after reading the full article it's not clear what was intended, but I think Eckel was probably referring to situations like the second one I described above.

Eric Melski
that is a article...just click the link
yesraaj
The article didn't really provide much context though - I suspect that Eric was talking about the book mentioned in the article
1800 INFORMATION
+1  A: 

new and delete are actually operators in C++ which you can override to provide your own customized memory management. Take a look at the example here.

Naveen
A: 

If you are comparing operator overloading between Java and C++, you wouldn't be talking about new and delete - Java doesn't expose enough memory management detail for new, and doesn't need delete.

You can't overload the other operators for pointer types - at least one argument must be a class or enumerated type, so he can't be talking about providing different operators for pointers.

So operators in C++ operate on values or const references to values.

It would be very unusual for operators which operator on values or const references to values to return anything other than a value.

Apart from obvious errors common to all C++ functions - returning a reference to a stack allocated object (which is the opposite of a memory leak), or returning a reference to an object created with new rather than a value (which is usually done no more than once in a career before being learnt), it would be hard to come up with a scenario where the common operators have memory issues.

So there isn't any need to create multiple versions depending on whether the operands are stack or heap allocated based on normal patterns of use.

The arguments to an operator are objects passed as either values or references. There is no portable mechanism in C++ to test whether an object was allocated heap or stack. If the object was passed by value, it will always be on the stack. So if there was a requirement to change the behaviour of the operators for the two cases, it would not be possible to do so portably in C++. (you could, on many OSes, test whether the pointer to the object is in the space normally used for stack or the space normally used for heap, but that is neither portable nor entirely reliable.) (also, even if you could have operators which took two pointers as arguments, there's no reason to believe that the objects are heap allocated just because they are pointers. that information simply doesn't exist in C++)

The only duplication you get is for cases such as operator[] where the same operator is used as both an accessor and a mutator. Then it is normal to have a const and a non-const version, so you can set the value if the receiver is not const. That is a good thing - not being able to mutate (the publicly accessible state of) objects which have been marked constant.

Pete Kirkham