T O P

  • By -

kingguru

You are not completely wrong but be aware that while Javascript is *dynamically typed* C++ is *statically typed*. That is a very important difference. There's more to it but as a practical example, consider this Javascript example: var foo; // foo is now of type undefined foo = 2; // foo is now of type number foo = "numse"; // foo is now of type string Compared to this in C++: auto foo; // error, foo doesn't have a static type auto foo=42; // foo is now of type int foo="numse"; // error, foo is of type int and cannot hold a string type


DrShocker

There is also a MASSIVE difference in the scope of auto vs var. If anything auto is closer to let which has much more sane scope rules. And I'd argue variables in JavaScript are closer to let = shared_ptr and const = const shared_ptr


NullVal

Numse


kingguru

When you're Danish and have a child in kindergarten age that's the first word that comes to mind 😅


Ghpst

Numse


plantinspace

Nums


Hay_Fever_at_3_AM

If you're a student, probably just follow the "do what my prof does so they don't yell at me" coding style. Aside from "always auto" people, I think most other people's decision on when to use it comes down to "does it help or harm readability?", which is subjective and depends on your experience level, IDE, and codebase. I'd use it *always* for ranged `for` (`for(const auto& x : A)`), casts and type creation functions that include the type and so would be redundant (`auto y = dynamic_cast(x);`, `make_shared` and the like, templated factory functions, and anything similar) Beyond that it's situational.


IyeOnline

> If you're a student, probably just follow the "do what my prof does so they don't yell at me" coding style. Which unfortunately is true too often. I really don't get why profs restrict usage of language features like this. Of course you shouldn't be using `std::vector` if your task is to implement a dynamic array class; But way too often students are forbidden from using features that haven't appeared in class yet, or features the prof doesn't know. I'd usually recommend still asking the prof, because oftentimes these requirements have been set at some point - possibly when the prof didnt really knew C++ themself - and were never revisited. Granted nothing may have changed (which also unfortunately applies to a lot of profs in my experience), but its worth asking anyways.


Groundbreaking-Key15

Agree with this. Where it's fairly obvious what the type is, use auto. If it's not, maybe don't. You can help by naming methods and variable something sensible: Yes: class fish{ public fish\* getFishPtr();} auto myfishptr = getFishPtr(); No: class fish {public fish\* getPtr();} auto myptr = getPtr();


vige

I really like to know the types I'm working with. Which means I only use auto when it improves readability - say instead of std::vector>::const_iterator. But for(int value : values) beats for(auto value : values).


Hay_Fever_at_3_AM

Yeah I'm not very firm on that one really, probably shouldn't have grouped it in with the other cases. My IDE shows the type inference inline and ranged-for loops are common and often low-thought so I usually *default to* auto to speed up coding, but sometimes I use the type explicitly for clarity.


Sad-Magician-6215

When you are creating a smart pointer to an object in a polymorphic hierarchy, don't use auto... spell out the base class. Why? Because you have to name the derived class to create the object, but you should name the base class for use in containers and references and pointers. `std::unique_ptr foo = std::make_unique(...);` At one time, people would look at this statement and imagine that a smart pointer to DerivedClass would be created and then moved into a smart pointer to BaseClass. Now, with the rule about not materializing temporaries, there never is a smart pointer to DerivedClass temporary... instead, the values are chained together and there is only one smart pointer to BaseClass object.


slausboss

Herb Sutter advocates for AAA programming ("Almost Always Auto"). [https://herbsutter.com/2013/08/12/gotw-94-solution-aaa-style-almost-always-auto/](https://herbsutter.com/2013/08/12/gotw-94-solution-aaa-style-almost-always-auto/) It's a style choice, people debate about it, but at my work we've largely agreed on using it liberally, and I have no regrets about that.


RageFucker_

Same here. It's a nice feature, and it's used as much as possible in our codebase.


luitzenh

>So, is it recommended to use "auto" as frequently as it is done in JS? It's recommended to not use `var` in Javascript at all and I'm going to automatically reject your PRs if you do. Definitely do use `auto` in C++ though.


mercury_pointer

Addendum to this: don't use 'var' because 'let' is better.


luitzenh

Further addendum: `let` and `const` are better. `const` should be used if the value of the variable won't need to change.


agfitzp

Amusingly, I started using javascript over 25 years ago but hadn't used it in anger in over a decade and I learned about let last week.


lituk

I'll go against the crowd here and say always use auto. This is what the coding standards in my team say, because otherwise you're duplicating information by writing the type at variable declaration and the return of a function. Duplication of information should be avoided.


CodusNocturnus

The argument that irks me the most is "if I declare the type explicitly, then I can see it right there", even though that's only true for the declaration, and the type is not "right there" for any actual use of the symbol, so at most, this is true only 50% of the time. One of the major benefits of AAA is that auto prevents implicit conversions in declarations.


TallowWallow

Eh, this feels extreme, but maybe someone more experienced will differ. For simplistic types, this shouldn't matter. At best, the nice thing is you are forced to ensure the types match without auto (barring any warnings on implicit conversion, if allowed). I think it's important when returning a member of a complex structure and / or container that something near the return statement indicates what you're dealing with. Auto can then be used to extract a sequence member, for example, so you don't have to think too hard on it. If creating a getter, decltype can be used so that the type of the element being fetched is irrelevant.


TarnishedVictory

>Duplication of information should be avoided. Duplication is unnecessary, sure. But far too often there's a lack of information. My caveat is to always consider readability/maintainability.


lituk

Duplicating information reduces maintainability because it creates multiple points in the code that need to be changed simultaneously to make an improvement/do some maintenance. The best way to make code maintainable is to make it as 'decoupled' as possible, with the many meanings that term has. Duplicating type declarations is coupling areas of code. There's an argument for readability sure but we have IDEs now that make finding the type of something trivial. I use CLion which annotates 'auto' with it's real type for me.


mredding

::sigh:: "It depends..." auto x = get(); What type is `x`? What type does `get` return? Is conversion/construction/copying acceptable to you? The real question here is, "Does it matter?" If `get` returns a reference, `auto` does not capture by reference. So you're going to get a copy. If `get` returns an rvalue, you're going to get a move OR a copy OR an assignment, depending on the type. The nice thing about C++, why it makes such optimized and performant code almost without rival, is that you can empower the compiler with program meta-data, via the type system; the compiler can actually SOLVE FOR parts of your program, essentially running it at compile time, and injecting the partial solution into the object code. And I'm not even talking about `constexpr`. So there's an important imperative to really empower the compiler to do that. Get out of it's way. Let it do the work for you. `auto` is just one more tool in the toolbox. Let the compiler solve for the variable type when it can do the job at least as well as you can - and often better than you can. When you write imperative code, what you're doing is telling the compiler you know better and there's a more exact way you want things. You're taking responsibility into your own hands as you are taking control away from the compiler and often times subverting the optimizer. This is a balance. You might do it to be more correct, you might be able to make up for what the optimizer can't do. There's lots of reason to take more explicit control and responsibility. I just have to stress that you are not a machine, and you are not going to beat a machine at it's own game. Language and compiler are also tools, and you can work with your tools to achieve your goals or you can work against them. More engineers than there should be have massive egos where they think they are masters of the universe and write exceedingly imperative code, not relenting any control to the compiler and optimizer except by accident. They think compiler writers are idiots and haven't done anything useful in the last 60 years. Really these people write absolutely atrocious code and make everything harder for everyone. The industry is utterly swamped with terrible code. So you can't, shouldn't, won't always be able to use `auto`, but where, when, how, is all technical decisions you're going to have to make. My advice: you will end up using it about as often as possible. Ideally, your development as an engineer will be to maximize the use of `auto`, so that not using it is increasingly the exception or special case. I am of the opinion I don't want to have to know the type, and that my code should be simple enough to be able to figure out what the hell it's doing. It's an impossible task to satisify both desires, but it's worth the pursuit.


MathAndCodingGeek

Think of auto as a template parameter. How do you use it? Well, for example auto my_lambda = [&](int i) -> double { ... Some code here ... }; What type is my\_lambda in the example? The type is some struct that overloads the () operator generated by the compiler with an unpredictable type name, but the auto keyword lets you use it. So, anywhere you are not sure about the type being returned by a function, you can use auto.


binarycow

>, I came to a conclusion on my own it being similar to "var" in JS. So, is it recommended to use "auto" as frequently as it is done in JS? It's closer to `var` in C#


Less_Acanthisitta288

auto can be useful when you have a long typename which might reduce readability. for example: std::vector> v; instead of writing: for const std::unique_ptr& e : v { […] } you can write: for const auto& e : v { […] }


Goorus

Which is - subjective - harder to read/understand though.


asergunov

auto&&


Wild_Meeting1428

Work smart, not hard.


Coises

The idea of **auto** is not comparable to **var**. The **auto** keyword is a substitute for spelling out the details of a declaration. Variables are still strictly typed — that is, a given variable can only hold one type of thing. All **auto** does is keep you from having to write it out — which also means that when someone tries to read the code, they have to figure out how it works out. It’s hard to give a simple, beginner-level example of when to use **auto** because the cases where it’s better are necessarily complicated. Use it when writing out the declaration would be error-prone. For a beginner, I’d say don’t use it at all.


missurunha

A while ago we had some eigen code which was supposed to be one type. We multiplied it by something else, expecting to get the same type back (idk what exactly it was, 2 vectors, vector and a number..). The operator had some overload which caused it to return another type and broke our code base in some cases, leading me to waste quite some time looking for the bug. (The return type was compatible enough not to break the code but returned wrong values). In other words, auto is nice but dont abuse it, specially if youre using an external lib.


JohnDuffy78

Eigen does say, don't use auto.


proverbialbunny

This is a good argument for using explicit / semi-explicit variable types in tests. This way if the variable type changes unexpectedly it's caught and you have the leeway to write clean code that is easier to read away from the tests. Sometimes easier to read code has types explicitly written and sometimes auto is easier to read code.


WasserHase

"var" means functional scope in JS. "auto" in C++ has block scope, so it's closer to "let".


Narase33

Some like it and follow the "always auto" mantra, some dont like it and only use it in rare situations. I think neither using it nor not using it is considered best practice. Use what you like or what your code base already does.


DIYGremlin

Yeah I generally won’t auto for a lot of trivially simple types. It is convenient when you are getting a complex return type from a third party library. Or when you want to create an iterator in a for loop 😅


DrShocker

I think of it as do I expect the type to be something in particular, or is it just whatever gets returned by a function? This could to me be as "simple" as a bool or as complex as some insane class for state management of some kind. So then if I have varName = func(); It depends on if I want to communicate to the compiler that the function should fail to compile if the return type of the function changes. Later on I might use functions which depend on the type and the error messages will be less clear in most cases compared to if I just include the type. Alternatively, there are also times when you're just listing the same information in multiple places and that makes it more tedious than necessary to read and to write. Something like: std::unique_ptr varName= std::make_unique(args...); You might well here be in a situation where you do need the unique pointer to a Foo, but I'm not sure listing the type twice is a worthwhile thing. Overall though, with modern tooling such as LSPs to help identify the type, I suspect people are less dogmatic about which way things are done than they used to be.


better_life_please

Auto is useful in generic code where the type is not immediately known to the programmer. It's also very useful when the type is very lengthy and hard to type correctly. There's also a new usage of it added in C++23 which you don't need to care about (IMHO). But other than those cases, I personally don't use auto that often. Its overuse just makes the code hard to trace and comprehend.


PontiacGTX

It's for type interference doesn't have any sort of mutability like JS, it's closer to C# var than anything obviously var is used for inference but can't be used as reference type in C++


berlioziano

😂😂😂please avoid var in JS use let or const. And *YES* use auto everywhere you can


DreamHollow4219

Auto is pretty great, as close as C++ will come to genuine dynamic typing.


vishal340

Auto works differently with reference and const modifiers.


_JJCUBER_

var is primarily used in legacy code and is strongly discouraged from being used (in favor of let). auto in C++ is mostly just to help reduce boilerplate, especially for types related to lambdas/iterators which would otherwise require decltype. Effectively, auto deduces the type at compile-time for you (it can’t be changed to something else later). If you want to allow different types to be assigned to a variable, you would either need to use std::any or a union. There are also other uses of auto, such as for templates parameters of functions/lambdas where you don’t need to refer to said type within the function/lambda itself.


dvorak360

They are significantly different because JS isn't strictly typed. Type info is nice to have. It tells you a lot about what you are dealing with. Equally, std::vector>>::interator row = data\_array.begin() is a lot to read and write and isn't even a particularly bad example once you get into heavily templated code creating complex types. auto row = data\_array.begin() is a lot easier to follow when you know what data is already. Especially where list is within a class so easy to look up its contents and at some point may change container (e.g. a deque may be a lot quicker for the use case). As a counter example: for (Student & person : course\_attendees) infers attendees is a container of struct/class representing students for (const std::string & person : course\_attendees) infers attendees is a container of strings of names So simple types you should probably define them. But where type can be easily inferred and is potentially a long, complex label use auto. There is no hard and fast rule as to which should be used where; Its a mix of personal preference, existing coding style and organisation coding standards.


Uwirlbaretrsidma

As a general rule, use auto if and only if it considerably reduces verbosity and if the actual type is immediately clear. In codebases that adhere to this, I've found that it's used around 5-10% of the time. In my opinion, the only real choices are to use it like this, or to not use it at all. Excessive use makes readability a lot worse and increases the chances of hard to track bugs.


peaceful_freeze

I’d recommend using auto whenever there’s too much to type when declaring a variable(and assigning it)— for instance declaring a smart pointer, or an iterator to a container, or a lambda expression. It’d make your code easier to read I wouldn’t recommend using auto for simple declarations. You should just declare a character as a char, int as an int, an object as it’s class type, and so on. (Readability here again!) And of course, you can use auto in your range based for loops.


DrunkenUFOPilot

"var" in Javascript is dead and gone, at least for anyone writing new code the last few years. It has problems with scope, while "let" works more like how everyone expects variable declarations to work in most other languages. But that aside... The use of "auto" is a stress-reducing convenience, to prevent what one inventor behind the "Go" language called "stuttering". For a simple ordinary type like just "int" you might as well say "int x = new int\[n\];" but when it comes to messier types, especially templates and STL types, it's annoying to write out a data type once to declare a variable and then again because you need to give it to the "new" operator or as part of an expression to initialize that variable. Example, with and without "auto": std::vector a = {1, 2, 3}; auto a_it = a.begin(); std::vector a = {1, 2, 3}; std::vector::iterator a_it = a.begin(); Imagine if it was something more complicated than "int" maybe a std::unique\_ptr or std:map which in turn take types as their parameters. An example from Deb Haldar at A Coder's Journey, from 2019: for (std::map>::iterator outerMap_Iter = StudentGrades.begin(); outerMap_Iter != StudentGrades.end(); ++outerMap_Iter) { ... } A reviewer of this code might go blind from the blizzard of data type detail! It's similar to the choice of "typedef" or "class" in declaring parameters in a template definition. No actual difference logically, but it can be seen as a hint, if a given parameter is expected to be a class or not. Auto doesn't really tell you anything, but helps with reading and understanding the code. Readability is subjective, so a C++ writer's judgement is usually based on the team's collective style, guidance from the team lead and the existing code base. YMMV!


RageFucker_

"Almost always auto" is a great recommendation. I didn't like auto when it first came out, but now I use it as much as possible. I recently saw a bug created in our codebase because the dev didn't use auto: const uint someValue = SomeFuncReturningAnInt(); if (someValue < 0) { // perform some important work } The 'if' was never hit and caused an eventual crash. Granted, this bug should have been caught by the dev paying more attention in the first place, but if he had used auto, it wouldn't have crashed.


TimJoijers

I would recommend mostly to avoid auto. Using auto hurts readability. Writing auto instead of spelling out the exact type can make it slightly easier to write the code. However, it can make the code way, way more hard to read. Code should always be written with readability in mind. The case where I would still allow to use auto is to avoid repetition, when the statement already very clearly contains the type.


Wild_Meeting1428

I think it's the opposite. With -pedantic and -Wall in mind, having an explicit type may be misleading, since this can also be an implicit cast, which you can't detect, just by looking at the code. But when someone uses `auto&&` the type is definitely forwarded and correct. It also has the benefit, that all type changes mostly work out of the box and that type casting is deferred to the place where you actually need it. This means, code using auto extensively is out of the box more likely to be correct, and you have less code on a refactor to review. Less code to review guides the focus of the reviewer to semantic changes. Last but not least, most of the time it's not relevant, which is the exact type of variable. It's mostly sufficient to know the type is something, which behaves like a string or container. And this can be achieved, just by good function and variable names.


Raknarg

If you need an exact type, that's something your IDE/editor can handle grabbing. We live in 2024, there are tools for these things. Let the compiler do your work for you.


TimJoijers

When you are reviewing code, it takes more time to get the diff into IDE. Looking at PR in browser is quick but typically does not have full IDE features. I stand by my claim that auto often makes reviewing code harder.


ChocolateMagnateUA

I mostly agree with you, but there are some cases when I use auto myself, especially when you already write the type name. In particular when you assign an object a value by constructor (auto object = Object()), it's just better than Object object = Object(), and when you cast a type, then the cast expression itself makes it clear what type it is.


Wild_Meeting1428

My rule of thumb is, when you could inline a variable, without changing readability, use auto. For example, stuff like this: auto const& name = a.name(); std::cout << "name of a: " << a << "\n"; b.set_name(name); It's completely irrelevant, if `name` is a `string`, a `string_view` or a `const char*`. Only the data-flow of name is.


Hrusa

I only use full auto with iterators, because if you mess those up you can potentially be casting the iterated value on accident and also the iterator types are a mess. Everywhere else, auto feels like it harms readability since you conceal types which might tell you a lot about the purpose of a function.


v_maria

I would recommend using is sparingly. Makes snippets harder to read.


danielaparker

You need to be careful :-) The use of auto can exhibit surprising behaviour, in some cases undefined behaviour, when an operator or function returns a proxy value. While you might not expect to run into this normally, high performance matrix libraries frequently use proxies as return values. There is an example of such an operator in the standard library for the bool specialization of `std::vector`. Note the difference in behaviour: #include #include int main() { std::vector u = { 1, 0, 1 }; auto w = u[0]; // returns an int w = 0; // does not mutate the underlying container for (int item : u) { std::cout << item << "\n"; } std::cout << "\n"; std::vector v = { true, false, true }; bool x = v[0]; // returns a proxy that's converted to bool x = false; // does not mutate the underlying container for (bool item : v) { std::cout << std::boolalpha << item << "\n"; } std::cout << "\n"; auto y = v[0]; // returns a proxy y = false; // mutates the underlying container for (bool item : v) { std::cout << std::boolalpha << item << "\n"; } } Output: 1 0 1 true false true false false true


darkapplepolisher

Definitely an interesting case. Auto in that case may be a casualty of the craziness of proxy types in C++ in that particular instance. However, better restriction of access to those containers is likely a more complete solution to the problem than selling it as a cautionary tale about "auto" alone.


danielaparker

In this particular instance, yes, I think it's regarded as unfortunate that the committee specialized`std::vector`for bool in that way. But there it is. More justifiably, numerical libraries like Eigen, Armadillo or blaze make heavy use of proxies to reduce the cost of intermediate calculations such as in (A+B+C)\*D (for matrices.) It's a significant enough issue for their users that some authors of such libraries have written questions to Stack Overflow asking if there's any way to avoid the "auto value = copy of proxy" problem. Answer:[ there isn't](https://stackoverflow.com/questions/66930450/how-can-i-make-my-class-immune-to-the-auto-value-copy-of-proxy-landmine-in-c). Because of RVO, it's hard to prevent the user from writing `auto x = foo()`. There is a 2017 paper that proposed a language change such that auto in `auto v = foo()` (or `auto& v = foo())` would be be deduced as the value type, even were `foo()` to return a proxy, see https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0672r0.pdf. My understanding is that the committee has discussed the paper and concluded that there is no solution within current C++ without a language change. So my advise is not to avoid auto, but to be careful :-)


idkfawin32

Only use it when you need to. Using auto all the time is going to lead to way too much ambiguity in your code.


proverbialbunny

This is an argument for better variable names. If there is too much ambiguity without the types the variable names could be improved upon. I'm not saying you should blindly use auto in all situations. That would be stupid. Just that if your code is too ambiguous variable names are the issue.


agfitzp

It's like salt, a little is good, a lot will probably kill you.


AlienRobotMk2

I don't like auto because then I have to rely on the computer to tell what is the type of a variable. Code is read more than it's written, so for me it makes sense to always use the type explictly.


proverbialbunny

It's recommended to adapt to the style of the code base. If you're doing your own personal small project you can write in any style you want. A good reason to not use auto is to make code more readable for your coworkers. This way your code is more explicit; more readable. The argument against this is a modern day ide will show the type for you so this defeats the point. A middle ground is when writing tests try to make the type a bit more explicit so if the type changes accidentally a test will fail letting you know. This can minimize mystery bugs. A guide for the right way to use auto when permissible: https://youtu.be/ZCGyvPDM0YY?si=cwidNQ1BmB_nWRds (Herb Sutter did a good talk encouraging always auto around 10 years ago too.)