簡體   English   中英

在基於范圍的 for 循環中使用轉發引用有什么好處?

[英]What is the advantage of using forwarding references in range-based for loops?

如果我想執行只讀操作, const auto&就足夠了。 然而,我遇到了

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

最近幾次。 這讓我想知道:

auto&const auto&相比,在某些晦澀的極端情況下,使用轉發引用是否有一些性能優勢?

shared_ptr是模糊角落案例的嫌疑人)


更新我在收藏夾中找到的兩個示例:

迭代基本類型時使用 const 引用有什么缺點嗎?
我可以使用基於范圍的 for 循環輕松迭代 map 的值嗎?

請專注於這個問題:為什么我要在基於范圍的 for 循環中使用 auto&&?

我能看到的唯一優勢是當序列迭代器返回一個代理引用並且您需要以非常量的方式對該引用進行操作時。 例如考慮:

#include <vector>

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

這不會編譯,因為從iterator返回的 rvalue vector<bool>::reference不會綁定到非常量左值引用。 但這會起作用:

#include <vector>

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

盡管如此,除非您知道需要滿足這樣的用例,否則我不會以這種方式編碼。 也就是說,我不會無緣無故地這樣做,因為它確實會讓人們懷疑你在做什么。 如果我這樣做了,包含關於原因的評論也無妨:

#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&&將成為首選的解決方案。

auto&&通用引用與基於范圍的for循環一起使用的優勢在於您可以捕獲所獲得的內容。 對於大多數類型的迭代器,您可能會為某種類型T獲得T&T const& 有趣的情況是取消引用迭代器會產生一個臨時的:C++ 2011 有寬松的要求,迭代器不一定需要產生左值。 通用引用的使用與std::for_each()中的參數轉發匹配:

template <typename InIt, typename F>
F std::for_each(InIt it, InIt end, F f) {
    for (; it != end; ++it) {
        f(*it); // <---------------------- here
    }
    return f;
}

函數對象f可以區別對待T&T const&T 為什么基於范圍的for循環的主體應該不同? 當然,要真正利用使用通用引用推斷類型的優勢,您需要相應地傳遞它們:

for (auto&& x: range) {
    f(std::forward<decltype(x)>(x));
}

當然,使用std::forward()意味着您接受要從中移動的任何返回值。 我不知道這樣的對象在非模板代碼中是否有意義(還?)。 我可以想象使用通用引用可以為編譯器提供更多信息來做正確的事情。 在模板化代碼中,它不會對對象應該發生什么做出任何決定。

我幾乎總是使用auto&& 為什么在不必要的情況下會被邊緣情況咬傷? 打字也更短,我只是覺得它更......透明。 當您使用auto&& x ,您就會知道x每次都是*it

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM