在包含shared_ptr的地图上使用find_if会增加引用计数

时间:2019-05-12 12:58:07

标签: c++

我正在创建一个程序,该程序的地图包含shared_ptr。当我尝试使用std::find_if在其中查找元素时,shared_ptr的引用计数增加了。示例:

#include <iostream>
#include <memory>
#include <map>
#include <algorithm>


int main(void)
{
    std::map<int, std::shared_ptr<int>> map;
    map[1] = std::make_shared<int>(3);
    map[2] = std::make_shared<int>(5);
    map[4] = std::make_shared<int>(-2);

    auto it = std::find_if(map.begin(), map.end(),
        [](const std::pair<int, std::shared_ptr<int>> &elem) {
            std::cout << "find_if: " << elem.second.use_count() << std::endl;
            return *elem.second == 5;
        });

    std::cout << "main: " << it->second.use_count() << std::endl;
}

使用此代码,我得到的输出

find_if: 2
find_if: 2
main: 1

我不确定引用计数的增加是否正确。

我正在使用Visual Studio 2017。

1 个答案:

答案 0 :(得分:7)

问题是您的lambda参数的类型

const std::pair<int, std::shared_ptr<int>> &

...这与std::map<<int, std::shared_ptr<int>>>::value_type不对应(密钥类型缺少const)。

因此,要调用您的lambda,必须根据存储在std::pair<int, std::shared_ptr<int>>中的std::pair<const int, std::shared_ptr<int>>构造一个std::map类型的临时对象。

构造此对象时,将复制shared_ptr,因此必须增加其引用计数器。

如果将参数类型更改为

const std::pair<const int, std::shared_ptr<int>> &

...问题消失了。您也可以在此处使用const auto&代替完整类型。

1 如果在此处使用非const引用,则会出现编译器错误,因为无法从a初始化类型为std::pair<int, std::shared_ptr<int>>的引用std::pair<const int, std::shared_ptr<int>>,但使用const引用可以代替使用临时文件。