在基于范围的 for 循环中使用转发引用有什么好处?

const auto& 如果我想执行只读操作就足够了.然而,我遇到了

const auto& would suffice if I want to perform read-only operations. However, I have bumped into

for (auto&& e : v)  // v is non-const

最近几次.这让我想知道:

a couple of times recently. This makes me wonder:

auto&const auto& 相比,在一些晦涩的角落情况下,使用转发引用是否有一些性能优势?

Is it possible that in some obscure corner cases there is some performance benefit in using forwarding references, compared to auto& or const auto&?

(shared_ptr 是模糊的极端情况的嫌疑人)

(shared_ptr is a suspect for obscure corner cases)

更新我在收藏夹中找到的两个示例:

Update Two examples that I found in my favorites:

在迭代基本类型时使用 const 引用有什么缺点吗?
我可以使用基于范围的 for 循环轻松迭代地图的值吗?

请专注于这个问题:我为什么要使用 auto&&在基于范围的 for 循环中?

推荐答案

我能看到的唯一优势是当序列迭代器返回一个代理引用并且您需要以非常量的方式对该引用进行操作时.例如考虑:

The only advantage I can see is when the sequence iterator returns a proxy reference and you need to operate on that reference in a non-const way. For example consider:

#include <vector>

int main()
{
    std::vector<bool> v(10);
    for (auto& e : v)
        e = true;
}

这不会编译,因为从 iterator 返回的右值 vector::reference 不会绑定到非常量左值引用.但这会奏效:

This doesn't compile because rvalue vector<bool>::reference returned from the iterator won't bind to a non-const lvalue reference. But this will work:

#include <vector>

int main()
{
    std::vector<bool> v(10);
    for (auto&& e : v)
        e = true;
}

话虽如此,除非您知道需要满足这样的用例,否则我不会以这种方式编码.IE.我不会无缘无故地这样做,因为它确实会让人们想知道你在做什么.如果我这样做了,也可以在评论中说明原因:

All that being said, I wouldn't code this way unless you knew you needed to satisfy such a use case. I.e. I wouldn't do this gratuitously because it does cause people to wonder what you're up to. And if I did do it, it wouldn't hurt to include a comment as to why:

#include <vector>

int main()
{
    std::vector<bool> v(10);
    // using auto&& so that I can handle the rvalue reference
    //   returned for the vector<bool> case
    for (auto&& e : v)
        e = true;
}

编辑

我的最后一个案例应该是一个有意义的模板.如果您知道循环总是在处理代理引用,那么 auto 将与 auto&& 一样工作.但是当循环有时处理非代理引用,有时处理代理引用时,我认为 auto&& 将成为首选的解决方案.

This last case of mine should really be a template to make sense. If you know the loop is always handling a proxy reference, then auto would work as well as auto&&. But when the loop was sometimes handling non-proxy references and sometimes proxy-references, then I think auto&& would become the solution of choice.

相关文章