I l@ve RuBoard Previous Section Next Section

Solution

graphics/bulb_icon.gif

This puzzle demonstrates the difference between three kinds of initialization: default initialization, direct initialization, and copy initialization. It also contains one red herring that isn't initialization at all. Let's consider the cases one by one.



T t; 


This is default initialization. This code declares a variable named t, of type T, which is initialized using the default constructor T::T().



T t(); 


A red herring. At first glance, it may look like just another variable declaration. In reality, it's a function declaration for a function named t that takes no parameters and returns a T object by value. (If you can't see this at first, consider that the above code is no different from writing something like int f(); which is clearly a function declaration.)

Some people suggest writing "auto T t();" in an attempt to use the auto storage class to show that, yes, they really want a default-constructed variable named t of type T. Allow me license for a small rant here. For one thing, that won't work on a standard-conforming compiler; the compiler will still parse it as a function declaration, and then reject it because you can't specify an auto storage class for a return value. For another thing, even if it did work, it would be wrong-headed, because there's already a simpler way to do what's wanted. If you want a default-constructed variable t of type T, then just write "T t;" and quit trying to confuse the poor maintenance programmers with unnecessary subtlety. Always prefer simple solutions to cute solutions. Never write code that's any more subtle than necessary.



T t(u); 


Assuming u is not the name of a type, this is direct initialization. The variable t is initialized directly from the value of u by calling T::T(u). (If u is a type name, this is a declaration even if there is also a variable named u in scope; see above.)



T t = u; 


This is copy initialization. The variable t is always initialized using T's copy constructor, possibly after calling another function.

Common Mistake

graphics/commonmistake_icon.gif

This is always initialization; it is never assignment, and so it never calls T::operator=(). Yes, I know there's an "=" character in there, but don't let that throw you. That's just a syntax holdover from C, not an assignment operation.


Here are the semantics:

  • If u is of type T, this is the same as writing "T t(u);" and just calls T's copy constructor.

  • If u is of some other type, then this has the meaning "T t( T(u) );"梩hat is, u is first converted to a temporary T object, and then t is copy-constructed from that. Note, however, that in this case the compiler is allowed to optimize away the "extra" copy and convert it to the direct-initialization form (that is, make it the same as "T t(u);"). If your compiler does this, the copy constructor must still be accessible. But if the copy constructor has side effects, then you may not get the results you expect, because the copy constructor's side effects may or may not happen, depending on whether the compiler performs the optimization or not.

Guideline

graphics/guideline_icon.gif

Prefer using the form "T t(u);" instead of "T t = u;" where possible. The former usually works wherever the latter works, and has other advantages梖or example, it can take multiple parameters.


    I l@ve RuBoard Previous Section Next Section