范围for循环中的auto&&

在范围for循环中,下面代码并不一定可以获取右值属性。

unsigned short TopicPubClient::AddPublishCache(int thd_idx, std::vector<SharedBuffer>&& bufs) {
    auto& v = send_cache[thd_idx];
    for (auto&& e : bufs) { // e is lvalue-reference of type SharedBuffer&
        v.first.emplace_back(e);
    }
    return ++v.second;
}

上面的代码中,e并非右值,所以调用emplace_back时,需要手动调用std::move(e)才能达到预期效果。

From C++ forum

参考:Why use && in range for - C++ Forum

The difference between auto& and auto&& is relevant when elt’s initializer is an rvalue expression. The canonical example involves vector<bool>, whose iterator’s operator* typically returns a proxy type by value:

#include <vector>
int main()
{
    std::vector<bool> v{ true, false, true, false };   
    for (auto& elt: v) elt = true; // error: error: cannot bind non-const lvalue reference of type 'std::_Bit_reference&' to an rvalue of type 'std::_Bit_iterator::reference' {aka 'std::_Bit_reference'}
    for (auto&& elt: v) elt = true; // ok
}

http://coliru.stacked-crooked.com/a/493f418165dbfe4c

The first loop fails to compile, because it attempts to bind a lvalue reference to an rvalue.

NOTE

因为迭代vector<boo>产生的值时一个临时proxy对象,属于rvalue,这时必须用auto&&才能通过编译。

From cppreference

It is safe, and in fact, preferable in generic code, to use deduction to forwarding reference, for (auto&& var : sequence).

也就是说,在范围for循环中使用auto&&一般是在泛型编程中,涉及完美转发之类的情况下。