Topic: Scope of temporary objects


Author: bilbo@ireq.hydro.qc.ca (Louis Lamarche)
Date: 1 Sep 91 03:25:02 GMT
Raw View
Since C++ is a young language, implementation of compilers and
C++ translators differs. Here is an example of important
difference that can impact directly on the possibilities of
the language and on portability.

In my opinion, the scope of temporary/unnamed objects (Tobjects)
should be defined by the block in which they are created
( delimited by {} ) or at least a #pragma should be available
to do so.

1) Here is a code fragment showing differences between
   compilers.

#include <stream.h>

class X
{
   int value;
public:
   X(int);
   ~X();
   int getint();
};

X::X(int aValue) { cout << "X::X" << "\n";
                   value = aValue; }

X::~X() {cout << "X::~X" << "\n";}

int X::getint() { cout << "X::getint" << "\n";
                  return value; }

main()
{
   X(1);
   if (X(0).getint()) { cout << "case 0" << "\n"; }
   else
      if (X(1).getint()) { cout << "case 1" << "\n"; }
   return 0;
}

Cfront 2.0 gives:
warning: result of  constructor call expression not used (for X(1))
X::X
X::~X      <- Do not keep unnamed object
X::X
X::getint
X::~X      <- Scope of the Tobject reduced to if( ) expression
X::X
X::getint
X::~X      <- Scope of the Tobject reduced to if( ) expression
case 1

g++ 1.39 gives:
X::X
X::~X      <- Do not keep unnamed object
X::X
X::getint
X::~X      <- Scope of the Tobject reduced to if( ) expression
X::X
X::getint
X::~X      <- Scope of the Tobject reduced to if( ) expression
case 1

Borland C++ 2.0 gives:
X::X       <- Scope of the unnamed object is is main(){}
X::X
X::getint  <- Scope of the Tobject reduced to if( ) expression
X::~X
X::X
X::getint  <- Scope of the Tobject reduced to if( ) expression
X::~X
case 1
X::~X

Zortech 2.18 gives:
X::X       <- Scope of the unnamed object is main {}
X::X
X::getint  <- Scope of the Tobject is main(){}.
X::X
X::getint  <- Scope of the Tobject is main(){}.
case 1
X::~X
X::~X
X::~X

Now with an other main(),

main()
{
   X* xp = &X(0);
   if (xp->getint()) { cout << "case 0" << "\n"; }
   else
   {
      xp = &X(1);
      if (xp->getint()) { cout << "case 1" << "\n"; }
   }

   return 0;
}

Cfront2.0 gives:
error: address of non-lvalue (e.g. xp = &X(0))

g++ 1.39 gives:
X::X        <- creates first unnamed object
X::getint
X::X        <- creates second unnamed object
X::~X       <- deletes only one object !
X::getint
case 1

Borland C++ 2.0 and Zortech C++ 2.18 give:
X::X
X::getint   <- Scope of the unnamed object is main(){}.
X::X
X::getint   <- Scope of the unnamed object is main(){}.
case 1
X::~X
X::~X

Conclusion:

1) Cfront 2.0 and g++1.39 do not permit the "use" of
unnamed local objects. By "use" a mean take their address
and send them messages.
To be able to create unnamed objects the programmer must use
"new" and "delete" and eventually he must have a garbage
collector.
In some applications like real-time applications, garbage
collection is a risq. So these compilers becomes less
interesting.

2) Borlandc C++ 2.0 and Zortech C++ 2.18 permit the use of
unnamed object if their address is placed in a pointer at
construction. This enables to create/destroy a number of
unnamed objects that are placed on the stack the duration of
the {} delimited block. This reduces the need for garbage
collector in some application.

3) With Zortech 2.18 the scope of all temporary and unnamed objects
is the {} delimited block. This permits interesting constructions,
nearly extensions to the language.

#define select     { if(0) {}
#define when(a)      else if (a.getint() )
#define endselect  }
class Y  : public X etc
class Z  : public Y etc

main()
{
   select
      when (X(0))
      {
         cout << "case 0" << "\n";
      }
      when (Y(1))
      {
         cout << "case 1" << "\n";
      }
      when (Z(1))
      {
         cout << "case 2" << "\n";
      }
      when (A(1))
      {
         cout << "case 3" << "\n";
      }
   endselect

   return 0;
}

Here main exits when the first object returns true or when all
objects have been scanned. The result of Z(1) may depend on the
existence of X(0) and Y(1).

--
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
| Objective: Systems         |        Louis Lamarche
| 5430 Bernieres, St-Leonard |      bilbo@ireq.hydro.qc.ca
| QC, Canada, H1R 1N1        |