【问题标题】:Why does std::map behave strangely when passed by value into a lambda?为什么 std::map 在按值传递给 lambda 时表现异常?
【发布时间】:2011-06-08 15:04:21
【问题描述】:

我使用 c++ 0x 已经有一段时间了,并且非常喜欢新的 Lamba 函数设施。我已经习惯于在我的 lambda 声明中指定 [=] 来表明我想将外部作用域的变量按值传递给我的 lambda。

但是,今天我遇到了一个非常奇怪的 lambda 问题。我注意到在 for_each 期间将外部范围的映射按值传递给 Lamba 的工作方式很奇怪。这是一个显示问题的示例:

void LambdaOddnessOne ()
{
    map<int, wstring> str2int;
    str2int.insert(make_pair(1, L"one"));
    str2int.insert(make_pair(2, L"two"));

    vector<int> numbers;
    numbers.push_back(1);
    numbers.push_back(2);

    for_each ( numbers.begin(), numbers.end(), [=]( int num ) 
    {
        //Calling find() compiles and runs just fine
        if (str2int.find(num) != str2int.end())
        {
            //This won't compile... although it will outside the lambda
            str2int[num] = L"three";

            //Neither will this saying "4 overloads have no legal conversion for 'this' pointer"
            str2int.insert(make_pair(3, L"three"));
        }
    });

}

map 的许多方法都可以从 Lamba 内部调用(例如 find),但是许多其他方法在它们在 Lamba 外部编译得很好时会导致编译错误。

例如尝试使用 [ 运算符导致:

error C2678: binary '[' : no operator found which takes a left-hand operand of type 'const std::map<_Kty,_Ty>' (or there is no acceptable conversion)

尝试使用 .insert 函数导致:

error C2663: 'std::_Tree<_Traits>::insert' : 4 overloads have no legal conversion for 'this' pointer

有人理解这种不一致的行为吗?这只是MS编译器的问题吗?其他的我没试过。

【问题讨论】:

    标签: c++ c++11


    【解决方案1】:

    【讨论】:

    • 哎呀,是的,有一点头脑融化了......我的例子在通过引用传递时确实有效......虽然这确实提出了一个问题,但为什么地图不能按值传入?
    • @Benj:可以传值。您只是无法修改它,因为该值成为 lambda 的成员,而 lambda 默认为 const。如果要修改它,请将其声明为可变的。即[=]( int num ) mutable { }
    • 啊哈哈,有意思!是的,这确实解释了。我已经编辑了我原来的问题,以反映我通过价值传递的事实。谢谢大家:-)
    【解决方案2】:

    默认情况下,lambda 的函数调用运算符是 const(因此您无法修改按值传递的映射),但您可以通过编写 mutable 使其成为非 const:

    for_each ( numbers.begin(), numbers.end(), [=]( int num ) mutable
    {
        // ...
    

    欲了解更多信息,请参阅why does C++0x's lambda require “mutable” keyword for capture-by-value, by default?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-14
      • 2013-10-24
      • 1970-01-01
      • 1970-01-01
      • 2020-12-31
      • 2018-01-02
      • 2018-10-01
      • 1970-01-01
      相关资源
      最近更新 更多