Topic: copy constructor and operator=


Author: sachs@fnal.gov ("David Sachs")
Date: Mon, 2 Jun 2003 01:04:33 +0000 (UTC)
Raw View
> >   public:
> >     foo(const foo& a)
> >     {
> >       *this = a;
> >     }
> >     ...
>
> > It worked. But is it well defined?
> > If so, are there any pitfalls using this 'technique'?
>
> The pitfalls is that in general operator= expects to be called
> on an already initialized object.   While it might work, chances
> are it won't unless operator= is somehow hosed.

Don't forget that by the time operator= is invoked, every member of foo will
have been (default) initialized. If such initialization is reasonable, then
defining the copy constructor in terms of copy assignment is feasible. One
consideration is the overhead of initializing all members before overwriting
them.


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ron@sensor.com ("Ron Natalie")
Date: Mon, 2 Jun 2003 18:38:18 +0000 (UTC)
Raw View
""David Sachs"" <sachs@fnal.gov> wrote in message news:bbdda1$eec$1@info1.fnal.gov...

>
> Don't forget that by the time operator= is invoked, every member of foo will
> have been (default) initialized.

Nope, if it would only work that way C++ would be a nicer language.
Every member of foo that is NOT POD will be default initailized.   The POD's
may or may not have been initialized depending on context.


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Tue, 3 Jun 2003 17:58:26 +0000 (UTC)
Raw View
On Mon, 2 Jun 2003 18:38:18 +0000 (UTC), ron@sensor.com ("Ron Natalie")
wrote:

> ""David Sachs"" <sachs@fnal.gov> wrote in message news:bbdda1$eec$1@info1.fnal.gov...

> > Don't forget that by the time operator= is invoked, every member of foo will
> > have been (default) initialized.

> Nope, if it would only work that way C++ would be a nicer language.
> Every member of foo that is NOT POD will be default initailized.   The POD's
> may or may not have been initialized depending on context.

Don't forget that a POD has a trivial operator= which will work for an
uninitialized member.

You have still shown nothing to invalidate the practice.  Maybe you can
show a MI with virtual base example which will fail?

John

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ron@sensor.com ("Ron Natalie")
Date: Tue, 3 Jun 2003 22:27:27 +0000 (UTC)
Raw View
"John Potter" <jpotter@falcon.lhup.edu> wrote in message news:siqndvsqe8j5cin6b5eljavbbaap0tnma9@4ax.com...

>
> > > Don't forget that by the time operator= is invoked, every member of foo will
> > > have been (default) initialized.
>
> > Nope, if it would only work that way C++ would be a nicer language.
> > Every member of foo that is NOT POD will be default initailized.   The POD's
> > may or may not have been initialized depending on context.
>
> Don't forget that a POD has a trivial operator= which will work for an
> uninitialized member.

That doesn't make it valid.

> You have still shown nothing to invalidate the practice.  Maybe you can
> show a MI with virtual base example which will fail?

No just a POD will screw it up.   Let's have a class with an internally managed pointer.

struct C {
    T* t;
    int size;

   C() { t = new T[1]; size = 1; }
    ~C() { delete [] t; }

    C& operator=(const C& that) {
        delete [] t;
        size = that.size;
        t = new T[size];
        copy(that.t, that.t + size, t);
     }

    C(const C& that) {
        *this = that;        // bogus
    }
};

Since t is NEVER initialized in the copy construction case, the delete in the assignment op
invokes undefined behavior


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ron@sensor.com ("Ron Natalie")
Date: Sun, 25 May 2003 14:33:12 +0000 (UTC)
Raw View
"MJ" <c141592653589@hotmail.com> wrote in message news:423c153c.0305230938.32cb943f@posting.google.com...

>   public:
>     foo(const foo& a)
>     {
>       *this = a;
>     }
>     ...

> It worked. But is it well defined?
> If so, are there any pitfalls using this 'technique'?

The pitfalls is that in general operator= expects to be called
on an already initialized object.   While it might work, chances
are it won't unless operator= is somehow hosed.


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: c141592653589@hotmail.com (MJ)
Date: Tue, 27 May 2003 17:17:21 +0000 (UTC)
Raw View
ron@sensor.com ("Ron Natalie") wrote in message news:<xRtza.28016$wy4.2328@fe07.atl2.webusenet.com>...
> "MJ" <c141592653589@hotmail.com> wrote in message news:423c153c.0305230938.32cb943f@posting.google.com...
>
> >   public:
> >     foo(const foo& a)
> >     {
> >       *this = a;
> >     }
> >     ...
>
> > It worked. But is it well defined?
> > If so, are there any pitfalls using this 'technique'?
>
> The pitfalls is that in general operator= expects to be called
> on an already initialized object.   While it might work, chances
> are it won't unless operator= is somehow hosed.


I don't understand the word 'hosed'. What does it mean in this context?


Regards,
Michael

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ron@sensor.com ("Ron Natalie")
Date: Tue, 27 May 2003 18:00:40 +0000 (UTC)
Raw View
"MJ" <c141592653589@hotmail.com> wrote in message news:423c153c.0305260103.2f8bb0e6@posting.google.com...
\
> > The pitfalls is that in general operator= expects to be called
> > on an already initialized object.   While it might work, chances
> > are it won't unless operator= is somehow hosed.
>
>
> I don't understand the word 'hosed'. What does it mean in this context?
>
It means operator= needs to be not care about what is already in the
object.   In that case, it is almost certainly broken in some way for either
the copyconstruction or assignment case.   For example if there is a
dynamic allocation in the class:

    struct foo {
        boo* x:

         foo() {  x = new boo[100]; }
         ~boo() { delete [] x; }
    };

A proper operator = would most likely not want to just assign x in the source
object to x in the destination object.   It most likely wants to copy the elements
of x, or deallocate the old x and allocate a new one, etc...   None of these
can be done reliably in the copy-construction case because x has indeterminate
contents.   If you somehow caused it just to allcoate a new x array and put it there
without examining the old value of x, it would make copy construction work but
break the assignment.


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: c141592653589@hotmail.com (MJ)
Date: Fri, 23 May 2003 18:28:00 +0000 (UTC)
Raw View
Recently I saw the following code:

  class foo {
    ...
  public:
    foo(const foo& a)
    {
      *this = a;
    }
    ...
  };

Several classes were defined like this. In some of them a definition
of operator= was also included.

It worked. But is it well defined?
If so, are there any pitfalls using this 'technique'?


Michael

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jdennett@acm.org (James Dennett)
Date: Fri, 23 May 2003 20:20:29 +0000 (UTC)
Raw View
MJ wrote:
> Recently I saw the following code:
>
>   class foo {
>     ...
>   public:
>     foo(const foo& a)
>     {
>       *this = a;
>     }
>     ...
>   };
>
> Several classes were defined like this. In some of them a definition
> of operator= was also included.
>
> It worked. But is it well defined?
> If so, are there any pitfalls using this 'technique'?

It's often inefficient, becasue by the time the body of
the copy constructor runs all bases and members have already
been default constructed (in the absence of an initialization
list).  So, you construct them, and then you change their
values.  Not ideal.

More importantly, this mixes up two different ideas:
construction, which turns raw memory into an object, and
assignment, which changes one object value into another.

In some systems I have used an integral data member
with a known value (a "magic number") that is set on
construction, and can be checked as part of the class
invariant.  A copy constructor written as is yours
above would not satisfy the class invariant.

Another problem is for classes containing references,
const members, or other members that do not support
assignment: for these, copy construction makes sense,
but assignment doesn't.

The copy+swap idiom produces an assignment operation
from a copy constructor and a swap function in a pretty
exception-safe manner (possibly at some performance cost),
and is much more respectable that trying to define
construction in terms of assignment.

The worst related anti-idiom is use of in-place new to
implement assignment in terms of destruction and construction.
I won't reiterate here just how vile that is.

-- James.

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]