0

我想了解如何在 C++中使用Lambda 函数。

我正在使用自定义类型,如下所示:

struct my_toy_t {
    uint32_t    id;
    cv::Rect    box;
    cv::Mat     data;
}

typedef std::map<uint32_t, my_toy_t*> my_toy_map_t;

和:

int main() {

    my_toy_map_t input_map;
    my_toy_map_t output_map;

    // Some insertions in input_map...

    my_toy_map_t::iterator it;
    for (it = input_map.begin(); it != input_map.end(); ++it)
    {
        if (check_cond(it->second->box)) {
            output_map.insert(std::make_pair(it->first, it->second));
            input_map.erase(it->first);
        }
    }
    return 0;
}

bool check_cond(cv::Rect box) {
    if (box.area > 100)
        return true;
    else
        return false;
}

可能会注意到这my_toy_map_t只是一个std::map<uint32_t, my_toy_t*>,check_cond函数检查一个简单的条件。

是否可以使用 Lamba 函数翻译此代码(插入output map和删除input_mapifcheck_cond返回)?true

4

3 回答 3

2

首先,不需要指针。如果要避免复制,请使用std::reference_wrapper.

其次,您正在迭代容器,并在此过程中修改容器。这具有未定义的行为:先前的迭代器在插入/删除操作后无效。

您正在尝试做的是一个真正的过滤过程:获取容器中通过给定条件的元素,并用它填充另一个容器。
这可以通过标准库提供的某些通用算法轻松完成。例如,这里最简单的方法是使用std::copy_if

int main()
{
    std::copy_if( std::begin( input ) , std::end( input ) , std::inserter( output , std::end( output ) ) , [](const std::pair<uint32_t,my_toy_t>& pair ) { return pair->second.box.area > 100; });
}

如您所见,该函数std::copy_if()需要一个可调用实体作为过滤的谓词。在这种情况下,最简单的方法是传递一个 lambda 函数,并且因为您询问了如何使用 lambda 改进过滤。

参考:

于 2013-08-15T10:59:28.160 回答
2

可能是std::copy_ifstd::inserter

std::copy_if(input_map.begin(),input_map.end(),
             std::inserter(output_map,output_map.end()) ,
    [](const std::pair<uint32_t, my_toy_t*>& x ){ 
                             return (x.second)->box.area > 100;    
                              } 
                );

对于删除我可以想到这个:

my_toy_map_t temp;

std::remove_copy_if(input_map.begin(), input_map.end(), 
                    inserter(temp, temp.end()),
                    [](const std::pair<uint32_t, my_toy_t*>& x ){ 
                                 return (x.second)->box.area > 100;    
                                  } );

input_map.swap(temp);
于 2013-08-15T10:56:52.487 回答
1

可以将std::for_eachmutablelambda一起使用

std::for_each(input_map.begin(), input_map.end(),
         [&output_map](const std::pair<uint32_t,my_toy_t*> &it) mutable{
    //   ^^                                                     ^^^^^^^
         if (it.second->box.area > 100)
         {
             output_map.insert(it);
         }
    });

建议:你最好使用smart pointers + STL container而不是原始指针raw pointer + STL container

于 2013-08-15T10:54:44.043 回答