Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using find_if on map containing shared_ptr increases ref count

Tags:

c++

I'm creating a program which has a map containing shared_ptr's. And when I try to find an element in it with std::find_if, the reference count of the shared_ptr increases. Example:

#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;
}

With this code I get the output of

find_if: 2
find_if: 2
main: 1

and I'm not sure if the reference count increase is proper behaviour.

I'm using Visual Studio 2017.

like image 343
IlCapitano Avatar asked Mar 05 '23 00:03

IlCapitano


1 Answers

The problem is the type of the parameter of your lambda

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

...this does not correspond to std::map<<int, std::shared_ptr<int>>>::value_type (you are missing the const for the key type).

Thus, in order to call your lambda, a temporary object of type std::pair<int, std::shared_ptr<int>> has to be constructed from the std::pair<const int, std::shared_ptr<int>> stored in the std::map.

When this object is constructed, the shared_ptr is copied, so its reference counter has to be incremented.

If you change the type of the argument to

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

...the problem disapears. You could also use const auto& instead of the full type here.

1 If you use a non-const reference here, you'll get a compiler error because you cannot initialize a reference of type std::pair<int, std::shared_ptr<int>> from a std::pair<const int, std::shared_ptr<int>>, but a const-reference allow a temporary to be used instead.

like image 160
Holt Avatar answered Mar 06 '23 14:03

Holt