在循环c++中使用auto

Using auto in loops c++

本文关键字:auto 循环 c++      更新时间:2023-10-16

我收到以下代码的有符号/无符号不匹配警告:

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

问题是,通过将0分配给i,它变成了int而不是size_t。那么什么更好呢:

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

或者这个:

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

或者你有更好的解决方案?我更喜欢第一个,因为它更加一致,它只使用size_t,而不是同时使用size_tauto出于同样的目的。

基于范围的循环可能是更清洁的解决方案:

for (const auto& i : a)
{
}

这里,i是对容器a的元素的const引用。

否则,如果需要索引,或者不想在整个范围内循环,可以使用decltype(a.size())获取类型。

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

根据您想在循环中做什么以及编译器的功能,基于范围的for循环可能是更好的解决方案。

您提出的所有解决方案在大多数情况下都不错,只是有一些细微的差异你的第一个解决方案实际上是更糟糕的选择,这正是你的编译器告诉你的。第二种解决方案更好,但如果您想避免直接定义类型以简化操作或将来进行一些更改,可以执行以下操作:

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

通过这种方式,可以将in类型绑定为始终相互匹配。

如果你使用了正确的文字,你会很好:0U。auto看到一个int类型的文字,所以这就是i的类型。加上U,它会看到一个无符号的int文字。否则,您可能会像其他人建议的那样使用decltype,特别是因为sizeof(size_t)可能大于sizeof(int)(如果在64位长模式下运行,则在Windows、OS X等上)。

为了尽可能保持常量正确,我通常会写:

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

它不是很简洁,但很明显,您想要一个初始化为n类型的0的变量(而nconst)。

讨论:

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

注意,对于小于int的类型,子运算结果会扩展到int(称为整数提升)。

这里有一个简单的&更清洁的解决方案使其发挥作用。

for(auto i: a)
{
}

在以下表达式的情况下,使用无符号类型会带来问题:

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

我提出两种选择。第一个(编辑选择):

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

如果你可以使用比size_t大的类型:

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

否则,如果有符号整数类型的操作数的类型可以表示无符号整数类型操作数的所有值,则无符号整数型操作数应转换为有符号整数型的操作数类型。[expr.arith.cov]

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

我希望这能有所帮助。

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

如果您需要访问索引以及实际元素,则可能是最干净的解决方案。

更新:

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

这将是Richard Smiths评论的一个变通方法,尽管它看起来不再那么干净了。