后一种形式比前一种有什么优势?
在 formfor(auto& v : vector)
中, 的类型v
被推断为对通过取消引用容器的迭代器类型获得的类型的左值引用。这意味着如果取消引用迭代器的结果是一个右值(想想std::vector<bool>
它返回一个代表对单个bool
值的引用的代理类型),那么代码将无法编译,因为左值引用不能绑定到右值。
当您编写 时for(auto&& v : vector)
,这是一个通用引用v
,这意味着在上述情况下, 的类型将被推导出为右值引用;或者在取消引用迭代器返回对容器元素的引用的通常情况下作为左值引用。所以它也适用于这种vector<bool>
情况。这就是为什么如果您计划修改循环内迭代的元素时应该首选该表单的原因。
如果后者显然是有利的,为什么我们通常会选择auto&
而不是?auto&&
你不应该。我能想到的唯一缺点auto&&
是它不能保证你对元素所做的更改一定会传播回容器,但这表明设计有问题,我认为不值得防范。
使新的基于范围的循环等同auto &&
于破坏现有代码吗?
我看不出它如何破坏现有代码,因为旧语法将继续像今天一样发挥作用。但是,如果您的意思是用新语法替换现有代码,那么如果您要替换的是auto const&
表单,它可能会产生影响。请参阅此示例。注意auto const&
版本如何调用const
成员函数,而其他两个调用非const
版本?用简洁版本替换第一个将更改被调用的成员函数。
它会对新代码产生实际影响吗?
同样,它与auto&&
今天使用的旧代码没有什么不同,因此不会有任何区别。如果您在不打算修改元素的地方使用它,那么编译器将不再阻止您意外地这样做,您可能会调用不同的重载,如上例所示。
这不会向初学者介绍他们的代码实际上等同于的陷阱auto &&
吗?
我不确定我理解你的意思,但如果你问初学者是否会在不知道的情况下编写代码,或者理解参考折叠的复杂性,那么是的,他们可能会。但这是您所链接的论文的既定目标之一。论点是,您可以远离一开始就教授那些困难的概念,而是向初学者介绍一种for
适用于所有事物的基于范围的循环的单一语法。就这一点而言,我认为语法有优点,但从正确性的角度来看,我不赞成它,因为如果我想要对元素进行只读访问,const
我宁愿使用它,然后简洁的语法似乎auto const&
不对称。