public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
From: "E. Robert Tisdale" <edwin@netwood.net>
To: egcs@egcs.cygnus.com
Subject: elided copy constructors
Date: Wed, 31 Mar 1999 23:46:00 -0000	[thread overview]
Message-ID: <36F2CDC1.8B4FEC4A@netwood.net> (raw)
Message-ID: <19990331234600.GyacNXlDDM4oKm29QERcL8Xz-ZTW1k1lbIWfKOWpZw0@z> (raw)

My egcs-2.90.29 980515 (egcs-1.0.3 release) compiler 
does not always elide copy constructors as permitted
by the ANSI C++ standard so I must devise a workaround
to void a costly copy of doomed objects which
won't be referenced again until they are destroyed.
The following test program illustrates the problem:

----------------------------------------------------------------------
// test.cc

#include<iostream>

class X {                       // a dynamic array class
  // representation
  int*  p;                      // pointer to a huge array
  int   n;                      // length of the huge array
  // constructors
  X(int* q, int k):             // private constructor definition
    p(q), n(k) { }
  public:
  explicit
  X(int k):                     // explicit constructor definition
    p(new int[k]), n(k) { }
  X(const X& x);                // copy constructor declaration
 ~X(void) {                     // destructor definition
    if (p) delete [] p; }
  // functions
  int   length(void) const { return n; }
  friend                        // salvage a doomed array
  X     salvage(X& x) { int* q = x.p; x.p = 0; return X(q, x.n); }
  // operators
  const
  int&  operator [](int j) const { return p[j]; }
  int&  operator [](int j)       { return p[j]; }
  };

X::X(const X& x):               // copy constructor definition
  p(new int[x.n]), n(x.n) {
  cerr << "The copy constructor was called!" << endl;
  for (int j = 0; j < n; j++)   // copy the array
    p[j] = x.p[j];
  }

// user defined functions

#define salvage(x) x
#define return(x) return salvage(x)

inline
X       f0(int n) {
  cerr << "The copy constructor may be called for f0(int)." << endl;
  return X(n);
  }
inline
X       f1(int n) {
  X     x(n);
  for (int j = 0; j < n; j++)   // Initialize x.
    x[j] = j;
  cerr << "The copy constructor may be called for f1(int)." << endl;
  return(x);
 }
inline
X       g0(X x) {
  cerr << "The copy constructor may be called for g0(X)." << endl;
  return salvage(x);
  }
inline
X       g1(const X& x) {
  cerr << "The copy constructor must be called for g1(const X&)." << endl;
  return x;
  }

int
main () {
  cerr << endl
       << "The copy constructor may be called for X x0 = f0(32);" << endl;
  X x0 = f0(32);
  cerr << endl
       << "The copy constructor may be called for X x1 = f1(32);" << endl;
  X x1 = f1(32);
  cerr << endl
       << "The copy constructor may be called for X y0 = g0(f0(32));" << endl;
  X y0 = g0(f0(32));
  cerr << endl
       << "The copy constructor may be called for X y1 = g1(x1);" << endl;
  X y1 = g1(x1);

  cerr << endl
       << "The copy constructor must be called for X z0 = y0;" << endl;
  X z0 = y0;
  return 0;
  }
----------------------------------------------------------------------

I compiled and ran `test' as follows:

----------------------------------------------------------------------
$ uname -rms
Linux 2.0.36 i686
$ g++ --version
egcs-2.90.29 980515 (egcs-1.0.3 release)
$ g++ -O2 -felide-constructors -o test test.cc
./test

The copy constructor may be called for X x0 = f0(32);
The copy constructor may be called for f0(int).

The copy constructor may be called for X x1 = f1(32);
The copy constructor may be called for f1(int).
The copy constructor was called!

The copy constructor may be called for X y0 = g0(f0(32));
The copy constructor may be called for f0(int).
The copy constructor may be called for g0(X).
The copy constructor was called!

The copy constructor may be called for X y1 = g1(x1);
The copy constructor must be called for g1(const X&).
The copy constructor was called!

The copy constructor must be called for X z0 = y0;
The copy constructor was called!
$ 
----------------------------------------------------------------------

After editing the `test.cc' source file
to comment out the first C preprocessor macro definition

// #define salvage(x) x

I compiled and ran `test' again as follows:

----------------------------------------------------------------------
$ g++ -O2 -felide-constructors -o test test.cc
$ ./test

The copy constructor may be called for X x0 = f0(32);
The copy constructor may be called for f0(int).

The copy constructor may be called for X x1 = f1(32);
The copy constructor may be called for f1(int).

The copy constructor may be called for X y0 = g0(f0(32));
The copy constructor may be called for f0(int).
The copy constructor may be called for g0(X).

The copy constructor may be called for X y1 = g1(x1);
The copy constructor must be called for g1(const X&).
The copy constructor was called!

The copy constructor must be called for X z0 = y0;
The copy constructor was called!
[edwin@localhost svmt]$ 
----------------------------------------------------------------------

Perhaps I shouldn't expect my C++ compiler to elide
the copy constructor in function g0(X) if it wasn't inline'd
but it I think that the C++ compiler should recognize
that x in function f1(int) is a reference to the return value
and initialize the return value with X(n)
instead of creating a temporary and copying it
to the return value upon return from f1(int).

My question is, "When should we expect the egcs compiler
to elide copy constructors as permitted by the standard?"

Meanwhile, I am interested in comments and suggestions
concerning workarounds.

Yes, I really do need to return by value.
No, I really don't want to do reference counting.
I am developing class libraries for application programmers

        http://www.netwood.net/~edwin/svmt/

The class library need not be portable but application programmers
should be able to write portable applications without worrying
about whether copy constructors are elided or not.

Thanks in advance, E. Robert Tisdale <edwin@netwood.net>

             reply	other threads:[~1999-03-31 23:46 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1999-03-19 14:23 E. Robert Tisdale [this message]
     [not found] ` < 36F2CDC1.8B4FEC4A@netwood.net >
1999-03-19 15:18   ` Martin v. Loewis
     [not found]     ` < 199903192313.AAA00798@mira.isdn.cs.tu-berlin.de >
1999-03-19 15:54       ` Mark Mitchell
     [not found]         ` < 199903192356.PAA03038@adsl-206-170-148-33.dsl.pacbell.net >
1999-03-19 19:20           ` Tim Hollebeek
1999-03-31 23:46             ` Tim Hollebeek
1999-03-20  6:26           ` espie
     [not found]             ` < 19990320142609.15873.qmail@quatramaran.ens.fr >
1999-03-20  7:18               ` Martin v. Loewis
     [not found]                 ` < 199903201510.QAA08826@mira.isdn.cs.tu-berlin.de >
1999-03-20  9:50                   ` Mark Mitchell
     [not found]                     ` < 199903201752.JAA04517@adsl-206-170-148-33.dsl.pacbell.net >
1999-03-20 11:16                       ` craig
1999-03-31 23:46                         ` craig
1999-03-31 23:46                     ` Mark Mitchell
1999-03-31 23:46                 ` Martin v. Loewis
1999-03-31 23:46             ` espie
1999-03-21  6:09           ` Gerald Pfeifer
1999-03-28  9:45             ` Mark Mitchell
1999-03-29 12:50               ` Gerald Pfeifer
1999-03-31 23:46                 ` Gerald Pfeifer
1999-03-31 23:46               ` Mark Mitchell
1999-03-31 23:46             ` Gerald Pfeifer
1999-03-21  8:41           ` New webpage? Providing egcs support Gerald Pfeifer
     [not found]             ` < Pine.GSO.4.10.9903211733410.1651-100000@markab.dbai.tuwien.ac.at >
1999-03-21  9:38               ` Mark Mitchell
1999-03-31 23:46                 ` Mark Mitchell
1999-03-21 11:08               ` Jeffrey A Law
1999-03-31 23:46                 ` Jeffrey A Law
1999-03-31 23:46             ` Gerald Pfeifer
1999-03-31 23:46         ` elided copy constructors Mark Mitchell
1999-03-31 23:46     ` Martin v. Loewis
1999-03-31 23:46 ` E. Robert Tisdale
1999-03-19 15:37 Timmy Mulligins
1999-03-31 23:46 ` Timmy Mulligins
     [not found] <36F2CDC1.8B4FEC4A.cygnus.egcs@netwood.net>
1999-03-20  1:12 ` Jason Merrill
1999-03-31 23:46   ` Jason Merrill

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=36F2CDC1.8B4FEC4A@netwood.net \
    --to=edwin@netwood.net \
    --cc=egcs@egcs.cygnus.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).