www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1999/10/02/12:58:06

From: horst DOT kraemer AT snafu DOT de (Horst Kraemer)
Newsgroups: comp.os.msdos.djgpp
Subject: Re: no copy-ctor for temps
Date: Sat, 02 Oct 1999 17:11:47 GMT
Organization: [Posted via] Interactive Networx
Lines: 115
Message-ID: <37f628ae.49715@news.snafu.de>
References: <eb8J3.1214$%K6 DOT 36 AT firefly> <37f564ff DOT 3448616 AT newsserver DOT cc DOT monash DOT edu DOT au>
NNTP-Posting-Host: n163-175.berlin.snafu.de
X-Newsreader: Forte Free Agent 1.11/32.235
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

On Sat, 02 Oct 1999 01:53:32 GMT, DavMac AT iname DOT com (Davin McCall)
wrote:

> On Fri, 01 Oct 1999 19:45:14 GMT, wemccaug AT prairienet DOT org (Wendy E.
> McCaughrin) wrote:
> 
> > The following example shows that 'gxx' will not invoke a copy-ctor
> > for temporaries, only for variables.
> 
> Are you saying that's bad?
> 
> The code you point out as not calling the copy-ctor instantiates a
> temporary instance of the class as a function parameter. The reason
> that the copy-ctor is not called is because no copy operation is
> performed - the temporary object is created directly on the stack
> before the function is called.

Or more precisely. For the call

       void TstCpy( Overflow );    // call by value


       TstCpy(Overflow(" I am a temporary\n"));

the compiler doesn't generate a temporary at all which is copied to
the actual parameter of TstCpy, although the formal description of the
language describes this semantically. Instead it constructs the
Overflow object directly in the place of the actual parameter of
TstCpy.

This behaviour is explicitly permissible according to the C++
Standard.

Another example:

complex c1(1,2);  // 1
complex c2 = complex(1,2);  // 2

Formally 1 is a direct-initialization c1 by the c'tor
complex(double,double) and 2 is a copy-initialization (not a call to
complex::operator= !!) of c2 via complex(const complex&) of a
temporary constructed by complex(double,double). The compiler is
allowed to elide the "useless" temporary and generate exactly the same
code as for 3.

This may have serious impacts if the copy-c'tor does something
different than the "regualar" c'tor and the programmer expects it to
be called. The programmer is obliged to implement a semantically
correct copy c'tor which _does_ create a copy such that a program
cannot tell it away from the original. He may not rely on side effects
of the copy-c'tor which other c'tors don't produce because he is not
sure if it is actually "called".

A peciliarity:


Say, your class defined a private copy-c'tor.

	private:
          Overflow(const Overflow&);


Now

	TstCpy(Overflow("Huh ?"));

wouldn't compile, although the compiler would not attempt to call the
copy-c'tor because it elides the creation of the temporary as an
optimization issue.

This sounds illogical but it isn't. An optimizing compiler may not
allow constructs which a non-optimizing compiler can't allow. The
legality of a language construct cannot depend on the optimization
level of a particular compiler.

The IBM support thought differently some time ago: The question why
the IBM C++ compiler does allow this construct with a private
copy-c'tor got the answer: That's because our compiler optimizes away
the call to the copy-c'tor...

[full quote available]


Many older compilers (like WATCOM and old Borland compilers) will
compile this program, though:

>------------------------------------------<
#include <stdio.h>
#include <stdlib.h>

struct X {
  X(int) {}
private:
  X(const X&);
};

void f(X) {}

int main(int argc, char *argv[])
{
  f(1); // 1
  X x(1); // OK
  X x=X(1); // 2
  return 0;
}

>------------------------------------------<

gcc 2.95 complains about 1 and 2. MS VC++ 6.0 complains about 2 but
accepts 1...


Regards
Horst

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019