C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Can I avoided a memory problem doing this?

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
achava@hotmail.com
Guest





PostPosted: Fri Jan 28, 2005 2:04 am    Post subject: Can I avoided a memory problem doing this? Reply with quote



Suppose I am overloading an operator for class Zigid and my method
looks like this:

Zigid &operator+(Zigid &A)
{
Zigid *Sum = new Zigid();
....
return *Sum;
}

The code runs just fine, but the method allocates memory dynamically
and leaves it to the caller to clean up. What I want to know is, "How
do I get the caller to delete the all memory pointed to by the
reference it returns?" In particular an object of the Zigid class must
allocate memory dynamically when it is being created, although this
does not necessarily happen in the constructor.
Any help appreciated.
Achava


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Ulrich Eckhardt
Guest





PostPosted: Fri Jan 28, 2005 11:21 am    Post subject: Re: Can I avoided a memory problem doing this? Reply with quote



[email]achava (AT) hotmail (DOT) com[/email] wrote:
Quote:
Suppose I am overloading an operator for class Zigid and my method
looks like this:

Zigid &operator+(Zigid &A)
{
Zigid *Sum = new Zigid();
...
return *Sum;
}

The code runs just fine, but the method allocates memory dynamically
and leaves it to the caller to clean up. What I want to know is, "How
do I get the caller to delete the all memory pointed to by the
reference it returns?" In particular an object of the Zigid class must
allocate memory dynamically when it is being created, although this
does not necessarily happen in the constructor.

Don't do this. When types have things like operator+, these types usually
behave like values not like objects. The difference is that values are a
mere aggregation of data, with little or no behaviour to them while objects
are mostly defined by their behaviour with little or no visible(public or
otherwise) data. This is not a strict rule, but a guideline.

Now, for values, the typical way to overload operator+ goes like this:

class value
{
value& operator+=( value const& rhs)
{ ...; return *this; }
};

value operator+( value const& v1, value const& v2)
{
value res(v1);
res += v2;
return res;
}

You don't make operator+ a memberfunction because the two involved objects
are all equally important, which is better expressed by a free function
taking the two objects. Then, operator+ delegates to operator+= which is a
member because there is one prominent object involved.

One last note: In case you have a Java background, forget about new - in
Java you need new to create a new object, in C++ you only need new when you
want to manage the lifetime of the object yourself, as opposed to managing
its lifetime with the scope.

Uli

--
FAQ: http://parashift.com/c++-faq-lite/

/* bittersweet C++ */
default: break;

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Daniel Krügler (ne Spange
Guest





PostPosted: Fri Jan 28, 2005 11:22 am    Post subject: Re: Can I avoided a memory problem doing this? Reply with quote



Hello Achava,

[email]achava (AT) hotmail (DOT) com[/email] schrieb:

Quote:
Suppose I am overloading an operator for class Zigid and my method
looks like this:

Zigid &operator+(Zigid &A)
{
Zigid *Sum = new Zigid();
...
return *Sum;
}

The code runs just fine, but the method allocates memory dynamically
and leaves it to the caller to clean up. What I want to know is, "How
do I get the caller to delete the all memory pointed to by the
reference it returns?" In particular an object of the Zigid class must
allocate memory dynamically when it is being created, although this
does not necessarily happen in the constructor.

Although the code might run fine, but it should be fixed as soon as

possible ;-)

Honestly, functions returning references to any kind of object should

- never return references of local objects of the function (No, you
didn't do that)
- never return references to non-local objects, where the caller has the
responsibility for
resource management (Yes, that does happen above!)

A signature of something like

T& foo();

implies, that the returned reference belongs to an automanaged object in
some broader sense:
I mean an extended version of self-management, that includes some other
possible mechanism of the
defining (yours!) module, e.g. a private table of Zigid objects, which
are free'd by your module's
framework in some internally and invisible manner.

Binary arithmetic operators usually return **value** objects and the
question arises, why you don't simply write

Zigid operator+(const Zigid &A) // No reference return type, const reference argument!
{
Zigid Sum = Zigid();
....
return Sum;
}

As you might have noticed, I additionally replaced your mutable argument
by an immutable one. This
another point of critique of your code: Why the hack should an argument
of any binary arithmetic operator
be mutable? - Be const-correct! It would be very unusual, if such an
operator **really** modifies one of its
arguments...

Greetings from Bremen,

Daniel Krügler



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Efrat Regev
Guest





PostPosted: Fri Jan 28, 2005 11:26 am    Post subject: Re: Can I avoided a memory problem doing this? Reply with quote

<achava (AT) hotmail (DOT) com> wrote

Quote:
Suppose I am overloading an operator for class Zigid and my method
looks like this:

Zigid &operator+(Zigid &A)
{
Zigid *Sum = new Zigid();
...
return *Sum;
}

The code runs just fine, but the method allocates memory dynamically
and leaves it to the caller to clean up. What I want to know is, "How
do I get the caller to delete the all memory pointed to by the

I think that your problem could be solved by some form of garbage
collection, which could be done using one of the following:
1. Using "smart pointers", which can deduce when to deallocate memory. You
can find discussions on this in (among others)
a. "Modern C++" by Alexandrescu
b. "C++ Templates: the Complete Guide" by Vadevoorde and Josuttis,
c. the boost::smart_ptr library
http://www.boost.org/libs/smart_ptr/smart_ptr.htm#Introduction by Dimov et.
al. (which you can use directly). Specifically, you might want to check out
http://www.boost.org/libs/smart_ptr/sp_techniques.html.
2. Alternatively, you might go for more general garbage collection, e.g., as
in http://www.hpl.hp.com/personal/Hans_Boehm/gc/, in which case you wouldn't
have to deallocate memory explicitly at all. (There seems to be a wide range
of opinions on the merits of using general garbage collection, however.)

HTH



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Victor Bazarov
Guest





PostPosted: Fri Jan 28, 2005 11:27 am    Post subject: Re: Can I avoided a memory problem doing this? Reply with quote

<achava (AT) hotmail (DOT) com> wrote...
Quote:
Suppose I am overloading an operator for class Zigid and my method
looks like this:

Zigid &operator+(Zigid &A)
{
Zigid *Sum = new Zigid();
...
return *Sum;
}

I take it this definition is inside the class, for the addition op,
right? I'll assume that.

Quote:
The code runs just fine, but the method allocates memory dynamically
and leaves it to the caller to clean up. What I want to know is, "How
do I get the caller to delete the all memory pointed to by the
reference it returns?"

It's ugly, but you can always do

Zigid &someZigid = otherZigid + thirdZigid;
...
delete &someZigid; // No need in 'someZigid' any longer.
// Makes 'someZigid' reference invalid.

Quote:
In particular an object of the Zigid class must
allocate memory dynamically when it is being created, although this
does not necessarily happen in the constructor.

I have two problems with your approach. First, it is often suboptimal
to use freestore where you could simply return a temporary. Second,
the addition operator should be able to take a temporary as its argument
and for that you need to declare the 'A' argument a reference to const.
Third, if operator+ doesn't change the *this object, it should be also
declared 'const'. Those are the basics, you can read about them and
other very useful things in "Effective C++" by Scott Meyers.

Your declaration/definition should be

Zigid operator+(Zigid const& A) const
{
Zigid temp;
...
return temp;
}

Another argument against free store: if you use more than one operator+
in one expression, who's going to clean up?

zig = zig1 + zig2 + zig3 + zig4; // where do all the intermediate
// results go? how do you catch them?

You need to rethink the interface, I guess.

V



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Nicola.Musatti@ObjectWay.
Guest





PostPosted: Sat Jan 29, 2005 4:28 am    Post subject: Re: Can I avoided a memory problem doing this? Reply with quote

The error lies in wanting to return by reference when you should return
by value. You should write:

// Note the const reference parameter
Zigid operator+(const Zigid &A)
{
Zigid Sum;
....
return Sum;
}

If you feel that returning Zigid's by value is too expensive do not
provide operator+ and use operator += instead.

Cheers,
Nicola Musatti


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
R.F. Pels
Guest





PostPosted: Sat Jan 29, 2005 4:34 am    Post subject: Re: Can I avoided a memory problem doing this? Reply with quote

[email]achava (AT) hotmail (DOT) com[/email] wrote:

Quote:
Zigid &operator+(Zigid &A)
{
Zigid *Sum = new Zigid();
...
return *Sum;
}

The code runs just fine, but the method allocates memory dynamically
and leaves it to the caller to clean up. What I want to know is, "How

Don't do that. Just return a new Zigid from operator+, that will circumvent
a lot of problems you mention.

Zigid operator+(const Zigid& that)
{
Zigid result(....);
...
return result;
}


--
Ruurd
..o.
...o
ooo

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
achava@hotmail.com
Guest





PostPosted: Sat Jan 29, 2005 5:35 am    Post subject: Re: Can I avoided a memory problem doing this? Reply with quote

Thank you all for your replies. I have rewritten my code to return the
object rather than a reference to the object, and no longer do I create
the object on the free store. I let the scope do the clean-up. I did
in fact work in Java before taking up C++ again after a long lapse, so
I got used to using new for everything.


Regards,
Achava


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Seungbeom Kim
Guest





PostPosted: Sun Jan 30, 2005 4:00 am    Post subject: Re: Can I avoided a memory problem doing this? Reply with quote

Ulrich Eckhardt wrote:

Quote:
Don't do this. When types have things like operator+, these types usually
behave like values not like objects. The difference is that values are a
mere aggregation of data, with little or no behaviour to them while objects
are mostly defined by their behaviour with little or no visible(public or
otherwise) data. This is not a strict rule, but a guideline.

* Even an int variable is an object by definition in C++.
* When you use an object, you use it as an l-value or an r-value.
Therefore "values" vs "objects" is not a very good way to name them.

I understand well your concept of different roles for objects, but you
can call them more appropriately as "value objects" and "entity objects".

--
Seungbeom Kim

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.