[comp.lang.c++] elementary question about c++

jima@hplsla.HP.COM ( Jim Adcock) (04/13/88)

/* Actually, this might be an interesting example.  The following
   program is about the same, except constructors and destructors
   make and destroy a value, and I'm using old i/o in order to
   make for easier decyphering of the resulting ..c intermediate
   file.

   The Million Dollar Question: what SHOULD the printf statement
   in main() print out ??? Explain your answer :-)
*/

#include <stdio.h>
class foo
{
public:
	long value;
        foo ()  { printf("cons\n"); value = 1000000;}
       ~foo ()  { printf("dest\n"); value = 0;}
};

foo bar() { foo a; return a; }
main ()   
{ 
    foo c = bar (); 
    printf("c.value = %d\n",c.value);
}

shopiro@alice.UUCP (04/16/88)

In article <6590034@hplsla.HP.COM>, jima@hplsla.UUCP writes:
> 
> /* The Million Dollar Question: what SHOULD the printf statement
>    in main() print out ??? Explain your answer :-)
> */
> 
> #include <stdio.h>
> class foo
> {
> public:
> 	long value;
>         foo ()  { printf("cons\n"); value = 1000000;}
>        ~foo ()  { printf("dest\n"); value = 0;}
> };
> 
> foo bar() { foo a; return a; }
> main ()   
> { 
>     foo c = bar ();   // *****
>     printf("c.value = %d\n",c.value);
> }

It should print

	c.value = 1000000

In the line marked with *****, c is initialized to be a copy of whatever
bar() returns.

In more detail, it is as if the programmer wrote

class foo
{
public:
	long value;
        foo ()  { printf("cons\n"); value = 1000000;}
        ~foo () { printf("dest\n"); value = 0;}
        foo(const foo& f) : value(f.value) {}  // this line supplied by compiler
};

The perhaps unfamiliar syntax in the new line just copies the source value
into the target value.

The function foo::foo(const foo&) is called a ``copy-initializer.''
It is used whenever a new foo is to be a copy of an old one, that is,

	1) a local foo is initialized from a foo

		{
			foo f = global_foo;  // or ... = <foo_expression>
			...
		}

	2) a foo is passed to a function

		void foo_func(foo x);

		foo_func(f);	// the local variable x in foo_func is initialized

	3) a foo is returned from a function

		foo func_foo();

		foo_func(func_foo());  // a local temp is initialized with the
				       // result of func_foo()

If a copy-initializer is not supplied by the programmer, the compiler
generates the default version, which looks like the following for a class
with arbitrary base classes and members.

class D : B1, B2 ... {
	T1	m1;	// m1 is a data member, T1 is a type
	T2	m2;
	...
};

D::D(const D& d) : B1(d.B1), B2(d.B2) ... m1(d.m1), m2(d.m2) ... {}

Each initialization is the copy-initialization for the appropriate type.
They are executed left to right.

Of course, such copy-initialization is usually optimized to ``blast the
bits from the source to the target''.

If you leave the ``const'' specification out, you won't be able to copy
a constant object.

Following the same principles, the default assignment function is

D&
D::operator=(const D& d)
{
	*(B1 *)this = (B1 &)d;
	*(B2 *)this = (B2 &)d;
	...
	m1 = d.m1;
	m2 = d.m2;
	...
	return *this;
}

It too is usually optimized to ``blast the bits.''
-- 
		Jonathan Shopiro
		AT&T Bell Laboratories, Murray Hill, NJ  07974
		research!shopiro   (201) 582-4179

jima@hplsla.HP.COM ( Jim Adcock) (04/20/88)

| It should print
| 
| 	c.value = 1000000
| 
| In the line marked with *****, c is initialized to be a copy of whatever
| bar() returns.

Okay, given that my local copy of the AT&T compiler (v1.2 ?) clearly
generates intermediate C code that performs the destructor operation
[setting c.value to zero] before the return of the function, thus
printing:

c.value = 0

is this a bug, or what ?

How WOULD one generate C code for this operation -- returning the
value of a structure, yet destroying the value of that structure
before the function returns ?