【问题标题】:Forcing auto to be a reference type in a range for loop强制 auto 成为循环范围内的引用类型
【发布时间】:2014-08-06 11:17:54
【问题描述】:

假设我有foo,它是一个已填充的std::vector<double>

我需要对这个向量的元素进行操作。我有写作的动力

for (auto it : foo){
   /*ToDo - Operate on 'it'*/
}

但这似乎不会写回foo,因为it是一个值类型:向量元素的深层副本已被获取。

我可以给auto 一些指导以使it 成为引用类型吗?那我就可以直接在it上操作了。

我怀疑我遗漏了一些琐碎的语法。

【问题讨论】:

  • 这是一个非常基本的问题。像“我如何在 C++ 中声明一个整数”之类的东西。你应该阅读book on C++ basics 而不是问这个问题,因为我担心如果你不这样做,你会有更多的问题。我会以“缺乏最低限度的理解”来结束这个问题,但我缺乏对此的代表,并且关闭的原因已被删除。
  • 一个非常基本的问题?我过去问我的广义相对论教授的问题可能被他认为是基本的。这个问题对我来说似乎很高级。

标签: c++ c++11 for-loop range auto


【解决方案1】:

最少的auto 参考

循环可以声明如下:

for (auto& it : foo) {
   //    ^ the additional & is needed
   /*ToDo - Operate on 'it'*/
}

这将允许it 成为foo 中每个元素的引用。

关于这些循环的“规范形式”存在一些争议,但在这种情况下,auto& 应该可以解决问题。

一般auto参考

在更一般的意义上(在容器的细节之外),以下循环有效(并且可能更可取)。

for (auto&& it : container) {
   //    ^ && used here
}

auto&& 允许绑定到左值和右值。当用于通用或一般情况(例如模板情况)时,此表单可能会达到所需的平衡(即引用、副本、prvalue/xvalue 返回(例如代理对象)等)。

喜欢一般的auto&&,但如果您必须具体说明表格,请使用更具体的变体(例如autoauto const& 等)。

为什么auto&& 更好?

正如此处的其他答案和 cmets 所述。为什么auto&& 更好?简单地说,它会做你认为在大多数情况下应该做的事情,请参阅 this proposalits update

与往常一样,Scott Meyers 的blog 也值得一读。

【讨论】:

  • 太完美了。因此,在许多方面,它的工作方式与模板专业化类似。
  • auto&& 更可取。
  • 因为它精确地反映了迭代器的 const/rvalue/whatever 语义。
  • @YogiBear:例如在std::vector<bool> 中管理代理
  • 对于那些想知道为什么auto&& 更可取的人,我强烈建议阅读 Scott Meyers 关于通用参考的文章:isocpp.org/blog/2012/11/… 基本上,auto&& 将在必要时变为 auto&,但也允许auto&&的r值优化
【解决方案2】:

我会使用auto&&

for (auto&& it : foo) {
    // bla
}

N3994基于范围的 For-Loops: The Next Generation (Revision 1)”中详细说明了原因,它可以更好地与 代理对象一起使用(例如来自std::vector<bool> 的那些)。

事实上,C++1z 的提议(Clang 3.5 SVN 在-std=c++1z 模式下已经支持)提议的语法是:

// c++1z only
for (it : foo) { 
    // bla
}

作为for (auto&& it : foo)的简写。

更新:N3994 提案是not voted into C++17 工作论文。

【讨论】:

  • 正如我尝试的那样,no-type 语法不再适用于 clang(在 3.6 及更高版本上测试)。 live demo
  • @alexolut 是的,这个信息现在已经过时了,因为 N3994 是 not voted into C++17。早期版本的 clang、gcc 和 msvc 中的实现已被删除。
【解决方案3】:

你可以使用:

for (auto&& it : foo){

}

auto &&auto & 更喜欢管理代理迭代器,就像std::vector<bool> 一样。

【讨论】:

    【解决方案4】:

    在许多方面,这种混淆源于多年来发展起来的将*& 绑定到类型而不是变量的约定。

    例如int* a真的是int *a;即a 是指向int 类型值的指针。

    这同样适用于引用:对于int& aa 是对int 类型值的引用。

    所以你真正想做的是写for (auto &it : foo) 所以it 是对auto 推断的类型的引用。然后你可以使用it 来操作底层的向量元素。这通常会写成

    for (auto& it : foo)

    接下来,您可能希望使用 r 值引用for (auto&& it : foo),这可能是最好的通用形式。

    【讨论】:

      猜你喜欢
      • 2014-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-14
      • 2012-07-07
      • 2013-06-06
      • 1970-01-01
      相关资源
      最近更新 更多