为什么std :: map :: const_iterator在std :: for_each期间调用std :: pair构造函数,但是一个简单的for循环却没有?

时间:2014-03-31 15:09:21

标签: c++ c++11 map stl lambda

我有一个稍微复杂的类数据成员,如下所示:

class BranchOutputRow
{
...
}

class Foo
{

public:

    // Slightly complex data member here
    std::map<boost::multiprecision::cpp_int, std::set<BranchOutputRow>> hits;

    void DoLoop1()
    {
        // This loop calls the std::pair<> constructor

        std::for_each(hits.cbegin(), hits.cend(),
        [&](std::pair<boost::multiprecision::cpp_int,
                      std::set<BranchOutputRow>> const & hit)
        {
            ...
        }
    }

    void DoLoop2()
    {
        // This loop does NOT call the std::pair<> constructor

        for (std::map<boost::multiprecision::cpp_int,
                      std::set<BranchOutputRow>>::const_iterator hitsPtr 
                    = hits.cbegin();
         hitsPtr != hits.cend();
         ++hitsPtr)
         {
             ...            
         }
    }

}

int main()
{
    Foo foo;
    foo.hits[1] = std::set<BranchOutputRow>();
    foo.hits[1].insert(BranchOutputRow());

    foo.DoLoop1(); // direct access to map object is not available
    foo.DoLoop2(); // direct access to map object is available
}

如上所述,我发现Loop#1调用std::pair构造函数,尽管lambda函数通过引用接受其参数。因此,在循环1中,我没有直接访问地图中的对象,而只是副本。在我的实际计划中,我需要直接访问;因此,我必须使用循环2指示的版本。

(事实上,循环2 调用std::pair构造函数 - 并不意外 - 并且确实提供了对地图中对象的直接访问。)

我认为std::for_each会经过精心设计,以提供与for循环相同的语义,例如循环2,因此不会调用std::pair构造函数,而是直接允许访问地图中的对象。

为什么Loop 1会调用std::pair构造函数,尽管lambda函数通过引用接受它的参数?

1 个答案:

答案 0 :(得分:8)

value_type的{​​{1}}为std::map<K,V>。你的lambda需要std::pair<const K, V>。注意常数的差异。

转换是通过以下构造函数完成的:

std::pair<K,V>

(见{4}}上的(4)

转换的结果是临时的,临时文件可以绑定到const引用,因此您的代码可以正常工作。