【问题标题】:Using auto in loops c++在循环中使用自动 C++
【发布时间】:2013-07-04 12:25:44
【问题描述】:

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

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 出于同样的目的。

【问题讨论】:

  • auto i = 0u 怎么样?
  • 如果您的循环中需要索引,使用 int 怎么样?使用无符号索引会很快变得很糟糕。例如。当in 未签名时,i &lt; n - 1 是错误的。

标签: c++ loops c++11 auto


【解决方案1】:

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

for (const auto& i : a)
{

}

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

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

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

【讨论】:

  • 1 基于范围的循环的问题是索引不可用
  • 是的,这实际上是个大问题,我不想单独管理索引。
  • decltype(n) i = 0 会更短更清晰,不是吗?
  • 我不知道,但我要投赞成票 - 还有 4 个蹩脚的反对票 :)
  • @JDiMatteo 我同意detlype 不是很清楚。不幸的是,size_t 不能保证是正确的类型,否则容器不需要定义size_type。因此,如果我想确保使用正确的类型,我会在通用代码中使用它。但我不记得到目前为止必须这样做......
【解决方案2】:

根据您想要在循环中执行的操作以及编译器的功能,基于范围的 for 循环可能是更好的解决方案。

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

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

这样,您可以将in 类型绑定为始终相互匹配。

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • sizeof(0U) 总是 sizeof(size_t) 符合标准吗?
    • @Flexo:已编辑帖子以反映这一点并鼓励接受另一个答案。
    • -1。正如 Flexo 所说,这个答案的前半部分是错误的。后半部分基本上说“按照其他答案所说的去做”。如果你想“鼓励接受另一个答案”,你可以删除这个。
    • +1。刚刚了解了auto i= 0U,以及使用它的注意事项。 @ChronoKitsune 和 @Flexo 表明它是 OP 的 有效 但不是 最佳 解决方案。比decltype(a.size()) i=0 简洁的代码更干净。
    【解决方案4】:

    尽可能保持 const 正确,我通常这样写:

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

    这不是很简洁,但很明显,您希望将变量初始化为 n 类型的 0(而 nconst)。

    【讨论】:

      【解决方案5】:

      供讨论:

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

      请注意,对于小于int 的类型,减法结果会扩大到int(称为整数提升)。

      【讨论】:

        【解决方案6】:

        这是一个简单且更清洁的解决方案,可以让它发挥作用。

        for(auto i: a)
        {
        }
        

        【讨论】:

          【解决方案7】:

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

          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]

          【讨论】:

            【解决方案8】:
            for(auto n = a.size(), i = 0; i != n; ++i) {
            }
            

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

            更新:

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

            将是 Richard Smiths 评论的解决方法,尽管它看起来不再那么干净了。

            【讨论】:

            • 这是不正确的:在声明多个变量的auto 声明中,auto 是为每个变量独立推导的,如果推导的类型不同,则代码格式不正确。
            猜你喜欢
            • 2021-07-30
            • 2021-12-03
            • 1970-01-01
            • 1970-01-01
            • 2020-07-06
            • 2017-09-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多