auto-matically inititialized

Probably the most frequently used feature of C++11 is auto. Thanks to auto the compiler determines the type of a variable from its initializer. But what is the point with safety critical software?

The facts of auto

Automatic type deduction with auto is extremely convenient. First, you save a lot of unnecessary typing, in particular with challenging template expressions; second, the compiler is never - in opposite to the programmer - wrong.

The compiler uses the rules for template argument deduction for getting the type of the variable. Therefore, the outer const or volatile qualifier and references are removed. The next example shows this behaviour for constant and references.

But how can I be sure that a2 or a3 are of type int although I used a variable of type const int or const int& to initialize them? Sometimes I deduce it wrong. The answer is simple. The compiler knows the truth. The only declared class template GetType helps me a lot.

template <typename T>
classGetType;

If I use the only declared class template, the compiler will immediately complain. The definition is missing. That the characteristic I need. The compiler tells me exactly the type of the class template which can not be instantiated. At first to the extended source code. I disabled in the following source code the try to instantiate the only declared class template.

The GetType call in the lines 7,9, 12, and 14 uses the specifier decltype, which give you the exact type of the declared variable. The rest is only hard work. I successively commented out each GetType expression. A deep look into the error messages of the g++ compilers is very interesting.

The key expressions of the error message have a red line. Impressed? But once more. What is the point with safety critical software?

Initialize me!

auto determines its type from an initializer. That simply means. Without an initializer there is no type and therefore no variable. To say it positive. The compiler takes care that each type is initialized. That is a nice side effect of auto that is mentioned too rarely.

It makes no difference, whether you forgot to initialize a variable or didn't make it because of a wrong understanding of the language. The result is simply the same: undefined behaviour. With auto you can overcome this nasty errors. Be honest. Do you know all rules for the initialization of a variable? If yes, congratulations. If not, read the article default initialization and all referenced article in this article. I have no clue why they used the following statement: "objects with automatic storage duration (and their subobjects) are initialized to indeterminate values". This formulation causes more harm than good. Local variables will not be default initialized.

At first to the scope resolutions operator :: in line 25. :: addresses the global scope. In our case the variable n in line 14. Curiously enough, the automatic variable n in line 25 has the value 0. n has an undefined value and therefore the program has undefined behaviour. That will not hold for the variable mem of the class T2. mem returns an undefined value.

Two lines in the source code are especially interesting. First, the line 9. The current standard forbid it to initialize non-constant members of a class with auto. Therefore, I have to use the explicit type. This is from my perspective contra intuitive. Here is a discussion of the C++ standardization committee about this issue: article 3897.pdf. Second, the line 23. C++14 gets C++ string literals. You build them by using a C string literal ("") and add the suffix s (""s). For convenience I imported the in line 20: using namespace std::string_literals.

The output of the program is not so thrilling. Only for completeness. T2().mem has the value 0.

Refactorization

Just at the moment I want to conclude the post a new use case of auto come in my mind. auto very well supports the refactorization of your code. First, it's very easy to restructure your code if there is no type information. Second, the compiler takes automatically care of the right types. What does that mean? I give the answer in the form of a code snippet. At first, the code without auto.

int a= 5;
int b= 10;
int sum= a * b * 3;
int res= sum + 10;

When I replace the variable b of type in by a double 10.5, I have to adjust all dependant types. That is laborious and dangerous. I have to use the right types and to take care of narrowing and other intelligent phenomenons in C++.

The small variations of the code snippet always determines the right type of res, res2, or res3. That's the job of the compiler. The variable b2 in line 17 is of type double and therefore also res2; the variable sum3 in line 24 becomes due to the multiplication with the float literal 3.1f a float type and therefore also the finale result res3. To get the type from the compiler I use the typeid operator that is defined in the header typeinfo.

Here you get the results black on yellow.

Impressed? Me too.

What's next?

The initialization with curly braces {} has a lot in common with auto. It is used similarly often, helps to read the code, and makes your code safer. How? You will see in the next post.

Go to Leanpub/cpplibrary"What every professional C++ programmer should know about the C++ standard library".Get your e-book. Support my blog.

Comments

As far as I can tell "Local variables will not be defaultl initialized" should be "Local variables will be default initialized" in the case of objects with automatic storage, non-class non-array types "nothing is done" or they have "indeterminate value".

As to why indeterminate values, the basic explanation I see if the base C++ mantra; "You don't pay for what you don't use".

Note it wasn't until C++14 that the C++ standard made it clear what uses of indeterminate values were undefined behavior.