问题
When creating local variables, is it correct to use (const) auto& or auto?
e.g.:
SomeClass object;
const auto result = object.SomeMethod();
or const auto& result = object.SomeMethod();
Where SomeMethod() returns a non-primitive value - maybe another user-defined type.
My understanding is that const auto& result is correct since the result returned by SomeMethod() would call the copy constructor for the returned type. Please correct me if I am wrong.
What about for primitive types? I assume const auto sum = 1 + 2; is correct.
Does this also apply to range based for loops?
for(const auto& object : objects)
回答1:
auto and auto && cover most of the cases:
Use
autowhen you need a local copy. This will never produce a reference. The copy (or move) constructor must exist, but it might not get called, due to the copy elision optimization.Use
auto &&when you don't care if the object is local or not. Technically, this will always produce a reference, but if the initializer is a temporary (e.g., the function returns by value), it will behave essentially like your own local object.Also,
auto &&doesn't guarantee that the object will be modifiable, either. Given aconstobject or reference, it will deduceconst. However, modifiability is often assumed, given the specific context.
auto & and auto const & are a little more specific:
auto &guarantees that you are sharing the variable with something else. It is always a reference and never to a temporary.auto const &is likeauto &&, but provides read-only access.
What about for primitive/non-primitive types?
There is no difference.
Does this also apply to range based for loops?
Yes. Applying the above principles,
- Use
auto &&for the ability to modify and discard values of the sequence within the loop. (That is, unless the container provides a read-only view, such asstd::initializer_list, in which case it will be effectively anauto const &.) - Use
auto &to modify the values of the sequence in a meaningful way. - Use
auto const &for read-only access. - Use
autoto work with (modifiable) copies.
You also mention auto const with no reference. This works, but it's not very commonly used because there is seldom an advantage to read-only access to something that you already own.
回答2:
Yes, it is correct to use auto and auto& for local variables.
When getting the return type of a function, it is also correct to use auto&. This applies for range based for loops as well.
General rules for using auto are:
- Choose
auto xwhen you want to work with copies. - Choose
auto &xwhen you want to work with original items and may modify them. - Choose
auto const &xwhen you want to work with original items and will not modify them.
You can read more about the auto specifier here.
回答3:
auto uses the same mechanism of type deduction as templates, the only exception that I am aware of being that of brace-init lists, which are deduced by auto as std::initializer_list, but non-deduced in a template context.
auto x = expression;
works by first stripping all reference and cv qualifiers from the type of the right hand side expression, then matching the type. For example, if you have const int& f(){...} then auto x = f(); deduces x as int, and not const int&.
The other form,
auto& x = expression
does not strip the cv-qualifiers, so, using the example above, auto& x = f() deduces x as const int&. The other combinations just add cv qualifiers.
If you want your type to be always deduced with cv-ref qualifiers, use the infamous decltype(auto) in C++14, which uses the decltype type deduction rules.
So, in a nutshell, if you want copies, use auto, if you want references, use auto&. Use const whenever you want additional const-ness.
EDIT There is an additional use case,
auto&& x = expression;
which uses the reference-collapsing rules, same as in the case of forwarding references in template code. If expression is a lvalue, then x is a lvalue reference with the cv-qualifiers of expression. If expression is a rvalue, then x is a rvalue reference.
回答4:
When creating local variables, is it correct to use (const) auto& or auto?
Yes. The auto is nothing more than a compiler-deduced type, so use references where you would normally use references, and local (automatic) copies where you would normally use local copies. Whether or not to use a reference is independent of type deduction.
Where SomeMethod() returns a non-primitive value - maybe another user-defined type. My understanding is that const auto& result is correct since the result returned by SomeMethod() would call the copy constructor for the returned type. Please correct me if I am wrong.
Legal? Yes, with the const. Best practice? Probably not, no. At least, not with C++11. Especially not, if the value returned from SomeMethod() is already a temporary. You'll want to learn about C++11 move semantics, copy elision, and return value optimization: https://juanchopanzacpp.wordpress.com/2014/05/11/want-speed-dont-always-pass-by-value/
http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=199
https://isocpp.org/wiki/faq/ctors#return-by-value-optimization
What about for primitive types? I assume const auto sum = 1 + 2; is correct.
Yes, this is fine.
Does this also apply to range based for loops?
for(const auto& object : objects)
Yes, this is also fine. I write this sort of code at work all the time.
来源:https://stackoverflow.com/questions/29859796/c-auto-vs-auto