home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.c++
- Path: sparky!uunet!uunet.ca!frumious!pat
- From: pat@frumious.uucp (Patrick Smith)
- Subject: Re: Default assignment semantics
- Message-ID: <1992Sep15.025550.519@frumious.uucp>
- Date: Tue, 15 Sep 1992 02:55:50 GMT
- Reply-To: uunet.ca!frumious!pat
- References: <BuJs8K.Hzr@vcd.hp.com>
- Organization: None
- Lines: 76
-
- John Matthews <jm@vcd.hp.com> writes:
- |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.
-
- |Thus what I want to do in most of my assignment operators is
- |explicitly invoke the corresponding destructor and copy constructor.
-
- | X& X::operator=( const X& from )
- | {
- | this->~X(); // invoke destructor.
- | new(this) X(from); // invoke copy constructor.
- | return( *this );
- | }
-
-
- First, there's a small bug in your assignment operator -
- consider what happens if this == &from.
-
-
- More importantly, I would suggest that, while many specific assignment
- operators can be safely implemented this way, doing it as a general
- rule would not be a good idea. Consider, for example,
-
- class X {
- public:
- X& operator=(const X& from); // implemented as above
- virtual foo();
- };
-
- So far, so good. Now someone derives a new class:
-
- class Y : public X {
- public:
- Y& operator=(const Y& from);
- virtual foo();
- };
-
- Y& Y::operator=(const Y& from) {
- if (this != &from) {
- X::operator=(from); // Copy the X part
- // Do some customized copying of the Y stuff
- }
- }
-
- void g(Y& y1, Y& y2) {
- y1 = y2;
- y1.foo();
- }
-
- What does the call to y1.foo() inside g() do? Quite probably, it
- will call X::foo()!
-
- The problem is that Y's assignment operator calls X's assignment
- operator, which calls the destructor for y1 (and calls the wrong
- destructor, unless X's destructor is virtual), and then creates
- a new X object on top of y1. Not quite what the programmer intended!
-
- So if you use this style of assignment operator in a class X,
- then all(*) classes derived from X should avoid calling X's assignment
- operator inside their own assignment operators (or anywhere else,
- for that matter). In general, I'd think it would be worth a bit
- of extra coding to avoid this restriction.
-
- footnote:
- (*) Maybe you don't need to impose this restriction if X has no
- virtual functions and no virtual base classes. But that would
- depend on the implementation.
-
- --
- Patrick Smith
- uunet.ca!frumious!pat
- pat%frumious.uucp@uunet.ca
-