Path: utzoo!utgpu!water!watmath!clyde!att-cb!osu-cis!tut.cis.ohio-state.edu!mailrus!rutgers!bellcore!faline!thumper!ulysses!andante!alice!shopiro From: shopiro@alice.UUCP Newsgroups: comp.lang.c++ Subject: Re: elementary question about c++ Summary: copy-initialization does it Message-ID: <7813@alice.UUCP> Date: 16 Apr 88 03:57:16 GMT References: <1297@tekirl.TEK.COM> <6590034@hplsla.HP.COM> Organization: AT&T Bell Laboratories, Murray Hill NJ Lines: 106 Posted: Fri Apr 15 23:57:16 1988 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 > 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 ... = ... } 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