Topic: copy constr and/or assignment operator?


Author: Peter Niessen <niessen@ifh.de>
Date: Mon, 11 Dec 2000 17:44:04 GMT
Raw View
Hi,

do I need an assignment operator for a class if I have a copy
constructor? Do I need a copy constructor if I have an assignment
operator? My gcc version 2.95.2 19991024 on HP-UX goes into infinite
loops if I declare both like

 MyClass (const MyClass &OldMyClass);
 MyClass operator = (const MyClass &OldMyClass);

and it seems that is tries to do a copy in the parameter list although
it's declared with &. Thus the program ends up in an infinite loop
when doing

 MyClass mc1;
 MyClass mc2 (mc1);

in the main ().

I got this example from ,,Practical C++ Programming'' by S. Oualline.
He says that you get into trouble if you do not call by reference but
by value and suggests the above code.

Do you have a good recommendation where to read about the copy
constructor and assignment operator business?

Thanks for any answers,

Peter.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Daniel Frey <d.frey@aixigo.de>
Date: Mon, 11 Dec 2000 18:21:54 GMT
Raw View
Peter Niessen wrote:
>=20
> Hi,
>=20
> do I need an assignment operator for a class if I have a copy
> constructor? Do I need a copy constructor if I have an assignment
> operator? My gcc version 2.95.2 19991024 on HP-UX goes into infinite
> loops if I declare both like
>=20
>  MyClass (const MyClass &OldMyClass);
>  MyClass operator =3D (const MyClass &OldMyClass);

The loop is caused by the return type of operator=3D. Try returning a
reference:

   MyClass& operator =3D (const MyClass &OldMyClass);

and everything should work fine.

Regards, Daniel

--
Daniel Frey

aixigo AG - Financial Research and Education
Schlo=DF-Rahe-Str. 15, 52072 Aachen, Germany
Tel: +49 (0)241 936737-42, Fax: +49 (0)241 936737-99
EMail: D.Frey@aixigo.de, Web: http://www.aixigo.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: James Dennett <james@evtechnology.com>
Date: Mon, 11 Dec 2000 19:06:45 GMT
Raw View
Peter Niessen wrote:
>
> Hi,
>
> do I need an assignment operator for a class if I have a copy
> constructor? Do I need a copy constructor if I have an assignment
> operator? My gcc version 2.95.2 19991024 on HP-UX goes into infinite
> loops if I declare both like
>
>  MyClass (const MyClass &OldMyClass);
>  MyClass operator = (const MyClass &OldMyClass);
>
> and it seems that is tries to do a copy in the parameter list although
> it's declared with &. Thus the program ends up in an infinite loop
> when doing
>
>  MyClass mc1;
>  MyClass mc2 (mc1);
>
> in the main ().

First a meta-comment: this post is probably better suited to
comp.lang.c++.moderated if you're just interested in how C++
works.  (If you want to know why C++ is that way, or where the
Standard says so, you've come to the right place.  This is where
I come when I need a language lawyer ;)  I've set followup-to
comp.lang.c++.moderated.

If you would like us to tell you what you're doing wrong, it would
be useful to see your implementation of the copy constructor and
copy assignment operations for MyClass.

If the copy constructor looks like

MyClass::MyClass(const MyClass &other) { *this = other; }

then it shouldn't.  This might work in some cases, but
(a) it can be inefficient as members aren't initialised in the
    initialization list, and
(b) it might fail to work if the assignment operator relies on
    *this having been previously constructed (as it reasonably
    might).

If the assignment operator looks like

MyClass MyClass::operator = (const MyClass &other) {
 ~MyClass();
 new (this) MyClass(other);
 return *this;
}

then it shouldn't.  That approach isn't exception safe, and it
messes with the notion of object lifetimes in a way which is
likely to make Herb Sutter feel unwell if he reads this post.
The return by value is inefficient -- it uses the copy constructor
to make a copy of *this to be returned -- and makes your class
unsuitable for use in Standard library containers, which require
copy assignment to return a reference to *this.

Generally, unless a class is a dedicated resource management
class, it shouldn't need a special copy constructor/copy assignment
operator/destructor.  If you're in the business of writing resource
management classes then you absolutely need to understand the C++
notion of object lifetime, and the difference between assignment
and construction.  Some classes should not be copyable, and if you
don't like boost::noncopyable (the name may be wrong there) then
you should declare the copy constructor and copy assignment operators
private and provide no implementation for them in these cases.
You may wish to read http://www.boost.org/libs/utility/utility.htm
for documentation of boost::noncopyable.

> I got this example from ,,Practical C++ Programming'' by S. Oualline.
> He says that you get into trouble if you do not call by reference but
> by value and suggests the above code.

The declarations are close, except that operator = should return a
reference.  It's the implementations that you need to check.  And
more importantly, check why you need to implement these operations
and see if you can avoid it by using members which handle it for
you (e.g., replace a dynamically allocated array with a std::vector).
Custom copy semantics should be rare in high-level code.

> Do you have a good recommendation where to read about the copy
> constructor and assignment operator business?

The book "C++ FAQs" (Marshall Cline et al,  ISBN: 0201309831) covers
these issues quite clearly, IIRC.  For a good feel on exception safety,
Herb Sutter's "Exceptional C++" is the current recommendation.

-- James Dennett <jdennett@acm.org>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: John Kewley <kewley@cscs.ch>
Date: Tue, 12 Dec 2000 14:47:34 GMT
Raw View
Peter Niessen wrote:
>
> Hi,
> ...
>  MyClass (const MyClass &OldMyClass);
>  MyClass operator = (const MyClass &OldMyClass);
>
> and it seems that is tries to do a copy in the parameter list although
> it's declared with &. Thus the program ends up in an infinite loop
> ...

Since your return type for your assignment op is a value not a reference,
call by value semantics are used. This results in the copy constructor
being called, I suspect this will cause the loop.

For more on copy const and assignment see the Scott Meyers'
books "Effective C++" and/or "More Effective C++".
The Stan Lippman book "Inside the C++ Object Model" (or something like
that) goes into things in a lot more depth, but Meyers' articles cover
the "Essential"s.

Cheers,


--
John M. Kewley                             Tel: +41 (0) 91 610 8248
Senior Scientist                           Fax: +41 (0) 91 610 8282
Swiss Center for Scientific Computing      mailto:John.Kewley@cscs.ch
Via Cantonale, CH-6928 Manno, Switzerland  http://www.cscs.ch/%7Ekewley/

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]