我收到以下代码的警告签名/未签名不匹配:
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_t
和 auto
出于同样的目的。
基于范围的循环可能是一个更简洁的解决方案:
for (const auto& i : a)
{
}
在这里,
i
是对容器元素const
的a
引用。
否则,如果你需要索引,或者你不想遍历整个范围,你可以用
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++) {
}
通过这种方式,您可以绑定
i
和 n
类型以始终相互匹配。
如果你使用了正确的文字,你会没事的:0U。 auto 看到一个 int 类型的文字,所以这是 i 的类型。添加 U ,它将看到一个无符号整型文字。否则,您会像其他人建议的那样使用 decltype,特别是因为 sizeof(size_t) 可能大于 sizeof(int)(如果在 64 位长模式下运行,它在 Windows、OS X 等上)。
尽可能保持常量正确,我通常写:
const auto n(a.size());
for (auto i = decltype(n){0}; i < n; ++i)
{
}
不是很简洁,但是很明显你想要一个初始化为0的
n
类型的变量(而n
是const
)。
讨论:
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.conv]
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 评论的解决方法,尽管它看起来不再那么干净了。