Topic: copy ctor call elimination


Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1996/06/14
Raw View
jpotter@falcon.lhup.edu (John E. Potter) writes:

>Fergus Henderson (fjh@mundook.cs.mu.OZ.AU) wrote:
>: Alexander Krotoff <krotoff@boy.nmd.msu.ru> writes:
>
>: ] I have a question about initatialization of class objects described
>: ] in the CD section 8.5 p.11. There is a simple example:
>: ]
>: ] struct A {
>: ]          int s;
>: ]          A(int i) { s = i; }
>: ]          A(const A& x) { s = x.s + 2; }
>: ] };
>: ]
>: ] main(void)
>: ] {
>: ]         A a = A(1);
>: ]         printf ("%d\n", a.s);
>: ] }
>: ]
>: ] As seems to me, in this example copy ctor shall be used to initilaize
>: ] `a'. GNU G++ do not use it.
>[...]
>: GNU C++'s behaviour is allowed by the draft working
>: paper, section 12.8[class.copy]/15.
>
>: |   12.8  Copying class objects                               [class.copy]
>: |
>: |15 Whenever a class object is copied and the original object and the copy
>: |   have  the  same  type, if the implementation can prove that either the
>: |   original object or the copy will never again be  used  except  as  the
>: |   result  of  an implicit destructor call (_class.dtor_), an implementa-
>: |   tion is permitted to treat the original and the copy as two  different
>: |   ways  of  referring  to the same object and not perform a copy at all.
>
>This seems to allow not producing the copy while the original question
>involves not producing the original (temp).

I don't understand your distinction.  How can one tell which object
wasn't produced?  What observable difference results?

The program contained

 A a = A(1);

and the observed behaviour was that only one object was created
and no copy was performed.  This could be explained as either

 (a) the compiler optimized away `a'
 (b) the compiler optimized away the unnamed object
or (c) the compiler kept both `a' and the unnamed object
     but aliased them together in the same storage

but since their observational consequences are the same, I think
the distinction need not (and should not) concern us.

The text I quoted from [class.copy] clearly allows (c), and since (a)
and (b) are just different ways of describing the same result, it
allows them too.

>[...] if the copy constructor is made
>private in the above example, g++ still avoids it.  [...]
>Is this a bug or is there some other rule covering it?

It is not entirely clear from 12.8[class.copy]/15 whether or not an
implementation which optimizes away a copy as allowed by that section
is required to check access restrictions on the eliminated copy
constructor.  I believe it very likely that the committee's intent
is that the compiler is required to perform the check, but the absence
of wording similar to that in 12.2[class.temporary] makes it unclear.

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: jpotter@falcon.lhup.edu (John E. Potter)
Date: 1996/06/17
Raw View
Fergus Henderson (fjh@mundook.cs.mu.OZ.AU) wrote:
: jpotter@falcon.lhup.edu (John E. Potter) writes:

: >Fergus Henderson (fjh@mundook.cs.mu.OZ.AU) wrote:
: >: Alexander Krotoff <krotoff@boy.nmd.msu.ru> writes:
: >
: >: ] I have a question about initatialization of class objects described
: >: ] in the CD section 8.5 p.11. There is a simple example:

8.5 [dcl.init] in the public version.  Since /12 is now /11, I assume that
/11 is now /10.  Which could lead to 12.2.

: >: ]
: >: ] struct A {
: >: ]          int s;
: >: ]          A(int i) { s = i; }
: >: ]          A(const A& x) { s = x.s + 2; }
: >: ] };
: >: ]
: >: ] main(void)
: >: ] {
: >: ]         A a = A(1);
: >: ]         printf ("%d\n", a.s);
: >: ] }
: >: ]
: >: ] As seems to me, in this example copy ctor shall be used to initilaize
: >: ] `a'. GNU G++ do not use it.
: >[...]
: >: GNU C++'s behaviour is allowed by the draft working
: >: paper, section 12.8[class.copy]/15.
: >
: >: |   12.8  Copying class objects                          [class.copy]
: >
: >This seems to allow not producing the copy while the original question
: >involves not producing the original (temp).

: I don't understand your distinction.  How can one tell which object
: wasn't produced?  What observable difference results?

: The program contained

:  A a = A(1);

: and the observed behaviour was that only one object was created
: and no copy was performed.  This could be explained as either

:  (a) the compiler optimized away `a'
:  (b) the compiler optimized away the unnamed object
: or (c) the compiler kept both `a' and the unnamed object
:      but aliased them together in the same storage

: but since their observational consequences are the same, I think
: the distinction need not (and should not) concern us.

: The text I quoted from [class.copy] clearly allows (c), and since (a)
: and (b) are just different ways of describing the same result, it
: allows them too.

Agreed.  The original poster has the answer that side-affects of the
copy constructor are not guaranteed to happen.

: >[...] if the copy constructor is made
: >private in the above example, g++ still avoids it.  [...]
: >Is this a bug or is there some other rule covering it?

: It is not entirely clear from 12.8[class.copy]/15 whether or not an
: implementation which optimizes away a copy as allowed by that section
: is required to check access restrictions on the eliminated copy
: constructor.  I believe it very likely that the committee's intent
: is that the compiler is required to perform the check, but the absence
: of wording similar to that in 12.2[class.temporary] makes it unclear.

And that is left to the committee.

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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Alexander Krotoff <krotoff@boy.nmd.msu.ru>
Date: 1996/06/11
Raw View
Hello c++ gurus,

I have a question about initatialization of class objects described
in the CD section 8.5 p.11. There is a simple example:

struct A {
         int s;
         int s;
         A(int i) { s = i; }
         A(const A& x) { s = x.s + 2; }
};


main(void)
{
        A a = A(1);

        printf ("%d\n", a.s);
}

As seems to me, in this example copy ctor shall be used to initilaize
`a'. GNU G++ do not use it.

This is a message from Rohan LENARD:
-----------------------------------------------------------------------
Excerpts from BugReport.Gnu: 10-Jun-96 Re: copy ctor Alexander
Krotoff@such.s (3107*)

> >This is actually not a bug.  According to the DWP, g++ is allow to elide
> >the construction of the temporary for initialisation, thus the code is
> >equivalent to calling the ctor.

> As seems to me it is not true. According CD WP 8.5 ("Initialization")
> p11 in this case temporary shall not be created, and initialization
> must be performed by the constructor selected by best matching.

> Shall I ask it in the comp.std.c++ ?

That would be quickest. I couldn't find the example which I know exists
which shows what I'm trying to say :-(
------------------------------------------------------------------------

Who is right ?

 [Moderator's note: Rohan Lenard is right.
  For details see followup.  -fjh.]

Thank you,
--
Alexander N. Krotoff  krotoff@such.srcc.msu.su
Research Computer Center tel: +7(095)939-2638
Moscow State University  fax: +7(095)939-4430
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: clamage@Eng.sun.com (Steve Clamage)
Date: 1996/06/12
Raw View
In article PAA15002@boy.nmd.msu.ru, Alexander Krotoff <krotoff@boy.nmd.msu.ru> writes:
>
>I have a question about initatialization of class objects described
>in the CD section 8.5 p.11. There is a simple example:
>
>struct A {
>         int s;
>         A(int i) { s = i; }
>         A(const A& x) { s = x.s + 2; }
>};
>
>
>main(void)
>{
>        A a = A(1);
>        ...
>}
>
>As seems to me, in this example copy ctor shall be used to initilaize
>`a'. GNU G++ do not use it.
>
>This is a message from Rohan LENARD:
>-----------------------------------------------------------------------
>Excerpts from BugReport.Gnu: 10-Jun-96 Re: copy ctor Alexander
>Krotoff@such.s (3107*)
>
>> >This is actually not a bug.  According to the DWP, g++ is allow to elide
>> >the construction of the temporary for initialisation, thus the code is
>> >equivalent to calling the ctor.

The temporary object and copy constructor may be elided. See 12.2
"Temporary Objects" [class.temporary]. That rule is unchanged from the ARM.

BTW, section 8.5 p 11 in recent versions of the DWP does not concern
that topic. When referring to a version of the DWP, use the bracketed
section name. The bracketed names do not change, and are in the DWP
to aid in reconciling different versions.
---
Steve Clamage, stephen.clamage@eng.sun.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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1996/06/12
Raw View
Alexander Krotoff <krotoff@boy.nmd.msu.ru> writes:

] I have a question about initatialization of class objects described
] in the CD section 8.5 p.11. There is a simple example:
]
] struct A {
]          int s;
]          A(int i) { s = i; }
]          A(const A& x) { s = x.s + 2; }
] };
]
] main(void)
] {
]         A a = A(1);
]         printf ("%d\n", a.s);
] }
]
] As seems to me, in this example copy ctor shall be used to initilaize
] `a'. GNU G++ do not use it.
[...]
] This is a message from Rohan LENARD:
]
] > >This is actually not a bug.  According to the DWP, g++ is allow to elide
] > >the construction of the temporary for initialisation, thus the code is
] > >equivalent to calling the ctor.
]
] > As seems to me it is not true. According CD WP 8.5 ("Initialization")
] > p11 in this case temporary shall not be created, and initialization
] > must be performed by the constructor selected by best matching.
[...]
] Who is right ?

Rohan Lenard is right.  GNU C++'s behaviour is allowed by the draft working
paper, section 12.8[class.copy]/15.

|   12.8  Copying class objects                               [class.copy]
|
|15 Whenever a class object is copied and the original object and the copy
|   have  the  same  type, if the implementation can prove that either the
|   original object or the copy will never again be  used  except  as  the
|   result  of  an implicit destructor call (_class.dtor_), an implementa-
|   tion is permitted to treat the original and the copy as two  different
|   ways  of  referring  to the same object and not perform a copy at all.

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: jpotter@falcon.lhup.edu (John E. Potter)
Date: 1996/06/14
Raw View
Fergus Henderson (fjh@mundook.cs.mu.OZ.AU) wrote:
: Alexander Krotoff <krotoff@boy.nmd.msu.ru> writes:

: ] I have a question about initatialization of class objects described
: ] in the CD section 8.5 p.11. There is a simple example:
: ]
: ] struct A {
: ]          int s;
: ]          A(int i) { s = i; }
: ]          A(const A& x) { s = x.s + 2; }
: ] };
: ]
: ] main(void)
: ] {
: ]         A a = A(1);
: ]         printf ("%d\n", a.s);
: ] }
: ]
: ] As seems to me, in this example copy ctor shall be used to initilaize
: ] `a'. GNU G++ do not use it.
[...]
: GNU C++'s behaviour is allowed by the draft working
: paper, section 12.8[class.copy]/15.

: |   12.8  Copying class objects                               [class.copy]
: |
: |15 Whenever a class object is copied and the original object and the copy
: |   have  the  same  type, if the implementation can prove that either the
: |   original object or the copy will never again be  used  except  as  the
: |   result  of  an implicit destructor call (_class.dtor_), an implementa-
: |   tion is permitted to treat the original and the copy as two  different
: |   ways  of  referring  to the same object and not perform a copy at all.

This seems to allow not producing the copy while the original question
involves not producing the original (temp).  The examples under this
paragraph all show not producing a copy of an existing object.  When
these examples are run with g++, the copies are made even though they
could be eliminated.

It seems that the g++ behavior is allowed by 12.2[class.temporary]/1

- In some circumstances it might be necessary or convienient for the
- processor to generate a temporary object.  Precisely when such
- temporaries are introduced is implementation-defined.  Even when the
- creation of the temporary object is avoided, all the semantic
- restrictions must be respected as if the temporary object was created.
- [Example: even if the copy constructor is not called, all the
- semantic restrictions, such as accessibility, shall be satisfied. ]

This allows g++ to construct the object without first creating a
temporary and copying it.  However, if the copy constructor is made
private in the above example, g++ still avoids it.  This seems to
violate the restrictions at the end of 12.2/1.  Is this a bug or is
there some other rule covering it?

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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]