I am learning about automatic conversions in Accelerated C++, and the author states that the copy constructor is always called when you have a statement of the form
myClass myVar = 24;
Additionally he states that when you have statements of the form
myClass myVar;
myVar = 24;
what actually happens is that the myClass constructor that takes an integer as an argument is called to create an unnamed temporary variable of the type myClass, and then the assignment operator is called. The book was written in the year 2000, I believe. My question is whether or not these claims are still true. I learned about the move constructor and move assignment operations elsewhere, and I was wondering if those were called instead of the assignment operator/copy constructor.
Thank you for your time. I really appreciate it.
...the author states that the copy constructor is always called when you have a statement of the form
myClass myVar = 24;
Wrong.
Your book was written before C++11 became the new standard, so it doesn't mention move-semantics and the possibility that the move-constructor may be called. Moreover, it doesn't talk about copy-elision. Yes, it is true that a copy-constructor called may be invoked, but because of an optimization called copy-elison the compiler is allowed to remove a call from the copy/move-constructor. This is allowed even though it may affect the behavior of the program but note that this isn't guaranteed to happen on every compiler.
If you write a program to test this behavior you find that no copy/move constructor is called. Passing the command line argument -fno-elide-constructors
disables this elision and permits a call from the move-constructor.
The form of initialization your are using is called copy-initialization:
§ 8.5/15 Initializers
The initialization that occurs in the form
T x = a;
as well as in argument passing, function return, throwing an exception (15.1), handling an exception (15.3), and aggregate member initialization (8.5.1) is called copy-initialization. [ Note: Copy-initialization may invoke a move (12.8). — end note ]
Assuming copy-elision doesn't take place, the compiler will construct a temporary instance of the class in order to convert to the designated type. It will then copy or move-construct myVar
from this temporary using the copy-constructor or move-constructor. A move constructor takes precedence over a copy-constructor for rvalues, and will only be called if your class has an accessible move constructor; otherwise the copy-constructor is called.
If copy-elision doesn't happen, the compiler will initialize myVar
as if it had been copy-constructed from the right hand side. This is in accordance with the as-if rule which states that the compiler can perform optimizations given that it doesn't affect the observable behavior of the program.
Additionally he states that when you have statements of the form
myClass myVar; myVar = 24;
what actually happens is that the
myClass
constructor that takes an integer as an argument is called to create an unnamed temporary variable of the typemyClass
, and then the assignment operator is called. [...] My question is whether or not these claims are still true.
Yes, constructors do take part in implicit type conversions. From the latest draft, N3797:
§ 12.3 Conversions
Type conversions of class objects can be specified by constructors and by conversion functions. These conversions are called user-defined conversions and are used for implicit type conversions (Clause 4), for initialization (8.5), and for explicit type conversions (5.4, 5.2.9)
The explanation your author gave for that part was right except for the fact that the move-assignment operator will be called if it is accessible.