Re: Assignment operator=/copy constructor/temporaries, BROKEN!
On 2010-09-20 15:41:24 -0400, Fabrizio J Bonsignore said:
On Sep 19, 7:19 pm, Pete Becker <p...@versatilecoding.com> wrote:
On 2010-09-19 19:09:36 -0400, Fabrizio J Bonsignore said:
On Sep 18, 11:29 pm, Ian Collins <ian-n...@hotmail.com> wrote:
On 09/19/10 02:25 PM, Fabrizio J Bonsignore wrote:
some point, so why a copy constructor then? But see that strictly
speaking, the statement:
AO x = Function();
should call: the default constructor to build AO x; some copy
constructor to take the AO out of Function() to be used as argument...
to a call to the assignment operator between default constructed x and
the returned COPY of AO from AO Function();!!!
No, there is no assignment. x is constructed with AO's copy constructor.
Which explicitly ought to read AO x( Function() );
You can certainly write it that way if that's what you prefer.
and obviate the
operator = syntax, because such syntax seems to imply rather:
AO &x = *&Function();
Huh? How in the world does AO x end up implying that it's creating a reference?
or, take the address of the temporary, dereference it and reassign it
as a reference. The temporary was just moved from one implicit alias
to an explicit alias and memory is reused, plus saving a function
call. Anyway both objects are assumed to be built in a frame! And all
these operators are tautological but avoid a copy constructor call.
Basically we want such
statement to be optimized! But it is supposedly equivalent to:
AO x(Function());
Not supposedly, that's how it's defined. It's not an optimization.
I am used to think of AO x = Function(); as invoking a useful copy
constructor, but now such copy constructor looks ambiguous!
No, it's not ambiguous. There is no construct that takes the argument
that this code gives it. There are two constructors: a default
constructor, which doesn't take any arguments, so isn't suitable here;
and a copy constructor that takes its argument by non-const reference,
which can't be called with a temporary, so isn't suitable here.
Then AO
x( Function() ); is equivalent to:
AO *pFunction() {... return new AO;}
AO &AO::operator=(AO &x) {if (this==&x) return x; ...}
If you want to design a different language, go ahead. But that's not
C++, so there's really not much point in discussing it here.
AO *xp = pFunction(); //save the returned address, like a stack frame
AO &x = xp->operator=( *xp );//assign! instead of calling copy
constructor
or, get the address of the returned object, invoke operator= on it
with itself as argument (!) and assign the result to a reference to
object with the final by-value alias. This IS an assignment
construction, but not a copy (memory) construction, and it is optimum
since we avoid wasting an instance of the relevant object. The copy
constructor, implicit or explicit, here, is wasteful!
So unless the invoked copy constructor does anything beyond bitwise
copy,
Copy constructors never do bitwise copy in C++. They do
element-by-element copying. That's been the rule for twenty years.
the call to the constructor is only necessary to move the same
data from one stack frame to another frame? Or to move an address
value and then copy the same data into another heap area with another
address value? This is much clearer using a pointer directly:
AO Function() {
AO *p = new AO; //assign and initialize in the heap
AO &w = *p; //get a by value working reference
... //do some work on w
return w; //w returns a handle to the memory in p
}
AO &x = *&Function(); //x should point now to the content of *p!
or
AO *pFunction() {... return new AO;}
AO &x = *pFunction(); //&(x) != pFunction() but &x == pFunction() !!
Sure, but that's very risky, because the code is hiding a heap pointer
inside a reference.
and neither copy nor assignment constructor are called but the
relevant object is still referred to in the program and the assignment
was optimized, though we have to remember to delete &x; later because
it was built in the heap in Function(). A copy constructor here seems
like a way to manage memory so this final delete is not forgotten by
the system nor the user s responsibility...
Maybe. I don't know what you're trying to accomplish. I've just
responded to the misunderstanding about copy construction.
If we have instead:
AO x; //build a new AO
... //do process on x
AO z( x ); //copy constructor to get a new copy of x
... //do process on x and z
x = z; //discard x, call assignment operator...
then both copy constructor and assignment operator= are justified,
distinct and necessary and syntax and semantic match intuitively. We
need two memory areas for AO data. So the choice is between AO z( x );
and AO z = x; !!! Seems just an idiomatic preference, but now it does
not seem to be the same at all if the asignee comes from a function
call returned by value. Then return by value should be avoided for
efficiency and the copy constructor called explicitly always, or
always use pointers as return values and avoid using automatic
objects... which seems to be a bad contract with the language if you
have to avoid a valid construction when it is just a matter of
guaranteeing some efficiency.
I do not think it is very correct if I have to download the _source_
to the compiler, review it, modify it and bootstrap it (if at all
possible with my working version...),
No, that's certainly not correct. I don't see why you think this might
be necessary.
because the application is not
implementing well its specification! And then I find basic doubts
about the efficiency of its constructions violating the principle of
explicit semantic, which seems to have confused implementors.
Um, no. You've made incorrect statements several times about how copy
construction works; until you understand copy construction you're not
in a position to criticize implementors, who typically do understand
copy construction and its implications.
--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)