home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!pmafire!news.dell.com!swrinde!sdd.hp.com!ux1.cso.uiuc.edu!m.cs.uiuc.edu!sunb10.cs.uiuc.edu!sparc10.cs.uiuc.edu!pjl
- From: pjl@sparc10.cs.uiuc.edu (Paul Lucas)
- Newsgroups: comp.lang.c++
- Subject: Re: Default assignment semantics
- Message-ID: <1992Sep14.152055.5825@sunb10.cs.uiuc.edu>
- Date: 14 Sep 92 15:20:55 GMT
- References: <BuJs8K.Hzr@vcd.hp.com>
- Sender: news@sunb10.cs.uiuc.edu
- Distribution: usa
- Organization: University of Illinois at Urbana-Champaign
- Lines: 96
-
- In <BuJs8K.Hzr@vcd.hp.com> John Matthews <jm@vcd.hp.com> writes:
-
- >As I understand it, if a class does not have an explicitly defined
- >assignment operator, a default assignment operator is generated
- >by the compiler. This default operator simply does a member-wise
- >assignment. As has been pointed out many times, these semantics
- >are dangerous for classes that have pointers to dynamically created
- >objects as fields.
-
- *****> What many people seem to have forgotten is that this is not a
- new problem. Assigning good ol' structures in C that contain
- pointers is just as bad. One has to write a copy function in
- such cases because the default assignment doesn't work.
-
- >It seems to me that a more robust default assignment operator would
- >have the following semantics:
-
- > 1) Invoke the destructor of the object being assigned to.
- > 2) Invoke the copy constructor on the object being assigned
- > to, taking as an argument the object being assigned from.
-
- >In the case where a class has no user defined destructor or copy
- >constructor, the above semantics devolves to member-wise
- >assignment, just as before. However, for classes that have
- >user defined destructors and copy constructors, (as all classes
- >that have pointers to dynamic objects should) the above
- >semantics generates code that is much safer. Take for example a
- >String class, whose constructor allocates a character buffer for
- >a string, and whose destructor frees that buffer. The user-defined
- >copy constructor would construct its String object with a separately
- >allocated character buffer of the same size as its String argument,
- >and perform a string copy between the two character buffers.
-
- *****> Ah, but in some String classes, if the LHS's buffer is big
- enough to contain the RHS's, then the buffer is not
- deallocated. BTW, some String classes use chunks of buffers of
- a rounded-off size to lessen fragmentation.
-
- Also, chances are that someone who's writing a full-blown string
- class won't forget to overload assignment; it's code is trivial
- and is dwarfed by the remaining code.
-
- >Under the current default assignment operator semantics, for every
- >String assignment made, a character buffer is 'leaked', and two
- >pointers to the same buffer are made.
-
- *****> Not if the assignment operator is overloaded.
-
- >Under the above semantics,
- >however, the assignee String first has its buffer deallocated, and
- >then recieves a new buffer from the copy constructor, just like you
- >would expect.
-
- >Since this is not the semantics of the current assignment operator,
- >a user defined assignment operator needs to be defined whenever
- >a user defined destructor or copy constructor exists for a class.
-
- *****> Trivial.
-
- >Thus what I want to do in most of my assignment operators is
- >explicitly invoke the corresponding destructor and copy constructor.
-
- *****> Ah..."most." There are occasions, as I've already pointed out,
- when one doesn't want the d'tor called. To have this
- flexibility is probably part of the reason the assignment
- operator is as it is.
-
- >I know how to explicitly call a destructor on an object, but how do
- >you explicitly call a copy constructor on what used to be an object?
- >The only way I know of to do this is to overload operator new() with a
- >pointer argument. The overloaded new() operator would just return
- >the pointer. I could then write an assignment operator like the following
- >for any class X:
-
- > X& X::operator=( const X& from )
- > {
- > this->~X(); // invoke
- >destructor.
- > new(this) X(from); // invoke copy
- >constructor.
- > return( *this );
- > }
-
- >However overloading new seems a little kludgy when all I want to
- >do is call a constructor on a specific object reference.
-
- *****> Well, it still seems simpler to just overload the assigment
- operator.
-
- Another case that comes to mind if reference-counting;
- assignment operators for such classes do different things
- altogether.
- --
- - Paul J. Lucas University of Illinois
- AT&T Bell Laboratories at Urbana-Champaign
- Naperville, IL pjl@cs.uiuc.edu
-