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 |