和&&基于范围的循环和临时工作如何一起工作?

时间:2017-08-08 19:38:19

标签: c++ c++17

我看到了here下面的代码。描述说:

  

我们还可以使用auto&&捕获为转发参考。那是,   汽车和放大器;&安培;将解决自动&适用于左值参考,以及自动&&对于   rvalud参考。以下是捕获a的输出的示例   基于范围的循环在临时地图上循环。

如果引用的值是左值(我在这种情况下没有衰减),我确实理解auto&&auto&的衰减。我努力的方法是了解临时地图,基于循环的范围和移动的值如何协同工作。您是否愿意解释这些事情如何相互协作以及为什么可以从正在迭代的临时事件中移除。

#include <iostream>
#include <map>

std::map<std::string, int> get_map()
{
    return {
        { "hello", 1 },
        { "world", 2 },
        { "it's",  3 },
        { "me",    4 },
    };
}

int main() {
    for (auto&& [ k, v ] : get_map())
        std::cout << "k=" << k << " v=" << v << '\n';
}

1 个答案:

答案 0 :(得分:1)

在此示例中,auto&&有两种不同的用途,一种是可见的,一种是隐藏的。为了最大限度地冗长,你已经扩展到的循环:

{
    auto&& __range = get_map(); // the temporary get_map() is bound to a reference, which 
                                // extends its lifetime to the lifetime of the reference
                                // decltype(__range) is std::map<std::string, int>&&

    auto __begin = __range.begin();
    auto __end = __range.end();     // potential different type from __begin since C++17
    for (; __begin != __end; ++__begin) {
        auto&& __elem = *__begin;  // this is your structured binding declaration
                                   // *__begin is an lvalue, so decltype(__elem) is
                                   // std::pair<std::string const, int> const&


        // the actual destructuring here
        std::string const& k = std::get<0>(__elem);    
        int const& v         = std::get<1>(__elem);

        // now your body
        std::cout << "k=" << k << " v=" << v << '\n';
    }
}

因此:

  

为什么可以从正在迭代的临时移动。

此代码中的任何地方都没有发生任何变化。 map是在__range中构建的,这就是你要迭代的内容。它超出了最后一个支架的范围。

请注意:

  

如果引用的值是左值,我确实理解auto&&auto&的衰减

不太正确。首先,它不被称为“衰变” - 例如,当你将一个数组传递给一个函数时,衰变就会发生 - 它会衰变成一个指针。此外,auto&&不会崩溃为auto&。只是,如果初始值设定项是左值,auto&&auto&的行为方式相同。如果初始值设定项是右值,则auto&&有效(并产生右值引用),而auto&无法编译。