Re: Initialization and assignement
Paul Bibbings wrote:
Please consider the following code, which I have reduced from an
example in which I had initially employed debug print statements to
analyse which ctors/operators are called during the various
initializations and/or assignments.
class A {
int i_;
public:
A(): i_(0) { }
A(int i): i_(i) { }
A(const A& a) { i_ = a.i_; }
A& operator=(const A& a) { i_ = a.i_; return *this; }
A& operator=(const int i) { i_ = i; return *this; }
};
int main()
{
A a0; // #0
A a1(1); // #1
A a2(A(2)); // #2
A a3 = 3; // #3
A a4; // #4.a
a4 = 4; // #4.b
A a5(a0); // #5
return 0;
}
Surprisingly (to me), however, #2 did not resolve to:
#2: a: initialization of temporary using the 1-arg ctor;
b: initialization of a2 using the copy ctor
but rather the temporary + copy ctor was (apparently) optimized away
to the call:
A a2(2);
This is one of the many cases where an implementation has the liberty to
elide a copy ctor (even if that copy ctor has side effects). Indeed I
would be disappointed if an implementation did not, by default, apply
that optimisation.
that is:
#2: initialization of a2 using the 1-arg constructor (i = 2).
Likewise, #3 resolved to:
A a3(3).
This was not totally unexpected, but I did have the slight suspicion
that it might be effected using:
#3: a: initialization of temporary using the 1-arg ctor (i = 3)
b: initialization of a3 using the copy ctor.
It is allowed to do that but not required to.
(That the copy assignment operator= (const A&) was not called in any
of the instances completely matched expectations based on my
understanding of the differences between initialization and
assignment.)
It would be an error if an assignment operator was called in the context
of a declaration.
Given this, my question would be whether the resolutions for
initialization provided by my compiler (gcc 3.4.4, cygwin) for #2 and
#3 are what others might have expected and, in particular, whether
they are what *must* be expected to be in accordance with the
standard.
They are what I expect any reasonable implementation to do but the
standard does not require the optimisation. Please note that
accessibility of the copy ctor must be checked before elision is allowed.
e.g. in your code #3 requires that the one argument ctor has not been
declared to be explicit. IOWs the compiler must check that the temporary
can be constructed before eliding the copy ctor.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]