It seems that auto
was a fairly significant feature to be added in C++11 that seems to follow a lot of the newer languages. As with a language like Python, I ha
Like this developer, I hate auto
. Or rather, I hate how people misuse auto
.
I'm of the (strong) opinion that auto
is for helping you write generic code, not for reducing typing.
C++ is a language whose goal is to let you write robust code, not to minimize development time.
This is fairly obvious from many features of C++, but unfortunately a few of the newer ones like auto
that reduce typing mislead people into thinking they should start being lazy with typing.
In pre-auto
days, people used typedef
s, which was great because typedef
allowed the designer of the library to help you figure out what the return type should be, so that their library works as expected. When you use auto
, you take away that control from the class's designer and instead ask the compiler to figure out what the type should be, which removes one of the most powerful C++ tools from the toolbox and risks breaking their code.
Generally, if you use auto
, it should be because your code works for any reasonable type, not because you're just too lazy to write down the type that it should work with.
If you use auto
as a tool to help laziness, then what happens is that you eventually start introducing subtle bugs in your program, usually caused by implicit conversions that did not happen because you used auto
.
Unfortunately, these bugs are difficult to illustrate in a short example here because their brevity makes them less convincing than the actual examples that come up in a user project -- however, they occur easily in template-heavy code that expect certain implicit conversions to take place.
If you want an example, there is one here. A little note, though: before being tempted to jump and criticize the code: keep in mind that many well-known and mature libraries have been developed around such implicit conversions, and they are there because they solve problems that can be difficult if not impossible to solve otherwise. Try to figure out a better solution before criticizing them.
It makes your code a little harder, or tedious, to read. Imagine something like that:
auto output = doSomethingWithData(variables);
Now, to figure out the type of output, you'd have to track down signature of doSomethingWithData
function.
One of the drawbacks is that sometimes you can't declare const_iterator
with auto
. You will get ordinary (non const) iterator in this example of code taken from this question:
map<string,int> usa;
//...init usa
auto city_it = usa.find("New York");
One reason that I can think of is that you lose the opportunity to coerce the class that is returned. If your function or method returned a long 64 bit, and you only wanted a 32 unsigned int, then you lose the opportunity to control that.
Another irritating example:
for (auto i = 0; i < s.size(); ++i)
generates a warning (comparison between signed and unsigned integer expressions [-Wsign-compare]
), because i
is a signed int. To avoid this you need to write e.g.
for (auto i = 0U; i < s.size(); ++i)
or perhaps better:
for (auto i = 0ULL; i < s.size(); ++i)
This isn't a drawback of auto
in a principled way exactly, but in practical terms it seems to be an issue for some. Basically, some people either: a) treat auto
as a savior for types and shut their brain off when using it, or b) forget that auto
always deduces to value types. This causes people to do things like this:
auto x = my_obj.method_that_returns_reference();
Oops, we just deep copied some object. It's often either a bug or a performance fail. Then, you can swing the other way too:
const auto& stuff = *func_that_returns_unique_ptr();
Now you get a dangling reference. These problems aren't caused by auto
at all, so I don't consider them legitimate arguments against it. But it does seem like auto
makes these issue more common (from my personal experience), for the reasons I listed at the beginning.
I think given time people will adjust, and understand the division of labor: auto
deduces the underlying type, but you still want to think about reference-ness and const-ness. But it's taking a bit of time.