Hello again! In this video, we are going to look at the auto keyword.
The auto keyword goes back to C.
Originally, it meant that we want the memory used by a variable to be managed automatically, which
means a local variable on the stack.
Then people got tired of watching auto every time they defined a local variable, so it became optional
and eventually fell out of use.
More recently, C++ has recycled the keyword.
So now, when we say that a variable is auto, it means that we want the compiler to work out what type
to use, based on the initial value that we give.
So for example, if we have 'i' declared as auto with an initial value of 42, the compiler will look
at 42.
It's a literal of type int, and the compiler will deduce that i needs to be an
int for this to work. If we have a C style string, the compiler will deduce that it's an array
of const char. If we have a standard string literal, then the compiler will realize that we need a
standard string object and it'll pass this initializer as the argument to the constructor for the string.
So there are no temporary objects involved.
There are no implicit conversions.
The compiler will always use the exact type that's given by the initializer.
So that may not seem terribly interesting. Something that might be a bit more interesting is we can
use auto to simplify complex types.
In the last video, we were writing out iterator types in full.
So vector of int double colon iterator. Now that we know about auto, we can just put auto and the compiler
can work it out.
The compiler will know that begin() returns an iterator to whatever type vec is and the compiler
will know that vec is a vector of int.
So the compiler will know that "it" is an iterator to a vector of int.
Another useful feature is that sometimes, for example, in template programming, it's not always
easy to work out exactly what the type is. Or if you can work it out,
it's not,
it's not always easy to type it accurately.
So putting auto can save you a lot of trouble.
And then finally, as we'll see later on in the course (another teaser!), there are some situations in
C++ where you can't actually know what the type is.
So the compiler can actually create classes which have a type which is defined by the compiler.
So you can't actually find out what the type is.
So using auto is the only way.
Well, actually, there is one other way, but using auto is the best way to handle it.
So here's an example.
We have our
variables from the first slide. So i with a value 42 and the C-style and standard string
literals. Then we're going to multiply i by two just to prove that it is at least a number of some kind.
And then we're going to use this auto for the iterator, the iterator to the string.
So we're going to call begin() to get the first element of this string. And then the iterator returned
will have its type deduced by the compiler and then we can dereference that iterate and find out if
it got it right.
So there we are, i times two equals 84, so it has worked out that i is a number and not a string or
some other type.
And then the first element of str2 is 'H'.
So this has worked.
The compiler has got the correct type for the iterator and it's been able to dereference it.
So we said that auto doesn't perform any kind of temporary objects or type conversion.
It also doesn't take into account to const or reference.
So it really does literally just give the type that's required to make the initializer work.
So let's say we have a variable x, which is a reference to const int.
Then we have another variable y, which is declared auto and initialized from x.
So what do you think the type of y will be?
And there's a big hint here if you need it!
And now that we've defined y, are we allowed to modify it? So
pause the video and have a think about this.
Okay, so here's that code.
So we're going to print out the values of x and y to see what happens.
So first of all, let's see if it compiles.
Yep, it compiled. I actually compiled it earlier,
which is why it's so fast!
So y is not actually a const.
It's just a normal int.
And then as it's a normal int, we can increment it.
And then because y is not a reference to x, it is going to be value initialized, so it's actually going
to be a copy of x, so it's going to be an int with initial value 6.
And then if we increment it, the value of y will then be seven.
And as that's a copy it doesn't affect x.
So x is still 6.
So there's the solution.
The const and reference qualifiers are ignored, so auto y equals x is equivalent to saying int
y equals x and then y and x are independent variables. y is not const, so we can just modify it
and it won't affect x. If we do want to make y a const reference, then we need to actually add
the const and the reference ourselves.
So why is a reference to const whatever-the-type-of-x-is.
And then we get a compiler error. You cannot assigned to a variable that is const.
So now why is const.
And we don't just have to use literals or variables. We can also use the return value from a function.
So we have a function that returns five.
And then we can initialize x with the return value from this function.
So this function will be returned int, so x will have type int.
So is autoo really that good?
Is it something you should use all the time? And there are some very respected people in C++ who say
that you should use auto in every single declaration.
I don't agree with that.
And a lot of people don't, in fact. There are also some people who just don't like auto at all.
They say, "Oh, it makes your coat hard to read.
"You have to keep looking at what everything does to find out what the type is."
And there is actually quite a lot of truth in that. The type of an object gives you a lot of useful information
about what the object is and what it can do and what you can do with it.
So if you use auto, you remove all that information from the source code. So that can be quite a
loss.
On the other hand, there are some situations where it is useful.
So, for example, if the type is not interesting or doesn't matter at all. If the type doesn't provide
any useful information to the person reading the code.
Generally, the best time to use auto is when it makes the code clearer.
So I would say that the iterator is a good example of all the three.
You don't really care what kind of iterator it is.
It's an iterator into this vector. That's all you want to know.
And I think there's that code is much clearer than that code.
But, OK, it's a matter of opinion.
If it's difficult to discover the [type], then certainly auto can make template cods a lot easier
to read.
And there are some situations where you have no choice.
If you have a class which is generated by the compiler, you can't find out what the name is.
So you have to use auto.
Some situations where you should definitely not use auto. If you want to have a particular type. Because
it's possible that auto might not pick the one you want. The rules that the compiler uses for
working out what type something is can get pretty complicated, and it's not always easy for humans to
get the same solution that the compiler does.
So if you really want a particular type, then you should just put it in there, and not rely on hoping
that the compiler will do the right thing.
And also, if auto makes the code less clear, then don't use it.
For example, some code like this.
I mean - I have no idea what 'h' is supposed to be in that code.
Admittedly, these variable names are very badly chosen. h doesn't tell you anything on its own.
Maybe it makes more sense in the context of a program, but I would definitely want to have the information
that the type gives here, so that's somewhere I would not use auto.
Okay.
So there we are, a bit of food for thought.
Some controversy at the end of this one!
I'll see you next time.
But meanwhile, keep coding.