Using auto in loops c++

2020-02-05 06:49发布

问题:

I get warning signed/unsigned mismatch for the following code:

auto n = a.size();
for (auto i = 0; i < n; i++) {
}

The problem is that by assigning 0 to i it becomes int rather than size_t. So what is better:

size_t n = a.size();
for (size_t i = 0; i < n; i++) {
}

or this:

auto n = a.size();
for (size_t i = 0; i < n; i++) {
}

or maybe you have a better solution? I like the first one more because it is bit more consistent, it just uses size_t rather than both size_t and auto for the same purpose.

回答1:

A range based loop could be a cleaner solution:

for (const auto& i : a)
{

}

Here, i is a const reference to an element of container a.

Otherwise, if you need the index, or if you don't want to loop over the entire range, you can get the type with decltype(a.size()).

for (decltype(a.size()) i = 0; i < a.size(); ++i) {
}


回答2:

Depending on what you want to do inside the loop and the capabilities of your compiler, range-based for loop might be a better solution.

All of your presented solutions are not bad in most situations, with minor differences Your first solution is actually worse choice and that's exactly what your compiler tells you. Second solution is better but if you want to avoid directly defining types for simplicity or some future changes, you can do the following:

auto n = a.size();
for (decltype(n) i = 0; i < n; i++) {
}

This way you bind the i and n types to always match each other.



回答3:

If you used the correct literal, you'd be fine: 0U. auto sees a literal of type int, so that is the type of i. Add the U and it will see an unsigned int literal instead. Otherwise, you'd want to make use of decltype as others suggested, especially since sizeof(size_t) may be greater than sizeof(int) (it is on Windows, OS X, etc. if running in 64-bit long mode).



回答4:

Trying to be const-correct whenever possible, I usually write:

const auto n(a.size());
for (auto i = decltype(n){0}; i < n; ++i)
{
}

It isn't very concise, but it's clear that you want a variable initialized to 0 of n's type (and n is const).



回答5:

For discussion:

auto n = a.size();
for (auto i = n-n; i<n; ++i) {
}

Note that for types smaller than int, the substraction result widens to int (called integer promotion).



回答6:

Here's a simple & cleaner solution to make it work.

for(auto i: a)
{
}


回答7:

Using unsigned types would pose a problem in case of expressions like the following:

for (auto i = 0u; i < a.size() - k; ++i) ...

I propose two options instead. The first one (editors choice):

for (auto i = 0; i < static_cast<int>(a.size()); ++i) ...

and if you are fine with using a type which is bigger in size than size_t:

for (auto i = 0ll; i < a.size(); ++i) ...

Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type shall be converted to the type of the operand with signed integer type. [expr.arith.conv]



回答8:

for(auto n = a.size(), i = 0; i != n; ++i) {
}

...is probably the cleanest solution if you need the to access the index, as well as the actual element.

Update:

for(auto n = a.size(), i = n*0; i != n; ++i) {
}

Would be a workaround for Richard Smiths comment, although it doesn't look that clean anymore.