Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

keeping shared_ptr use_count() at 1

I was unable to find a similar question to this one, please direct me to one if I missed it! I am experimenting with smart pointers, and came to this scenario where I would like to keep the value returned by use_count() in a shared_ptr object to 1 (to practice optimizing code). Here is a snippet I am working with:

#include <iostream>
#include <memory>
#include <vector>

// testFunc: displays the use_count of each shared ptr in the list
void testFunc(const std::vector<std::shared_ptr<int>> &list) {
    // reference each shared ptr in the list and display their use_count
    for (auto &elem : list) {
        std::cout << elem.use_count() << std::endl;
    }   
} // testFunc()

int main() {
    // allocate shared ptr instance of an int
    auto sharedTest = std::make_shared<int>(11);

    // allocate another shared ptr instance of another int
    auto anotherSharedTest = std::make_shared<int>(22);

    // use std::move to prevent another copy of the shared ptrs from being created
    testFunc({ std::move(sharedTest), std::move(anotherSharedTest) }); 

    return 0;
} // main()

The output by this program is

2
2

since the use_count of both shared ptrs is 2. Can anyone show me why I cannot keep them at 1? I suspect that "passing" the vector to testFunc is creating a copy of each shared ptr when the entire vector is being passed, however this surprises me since I am passing the vector by reference. Any input is greatly appreciated!

like image 621
v.p. Avatar asked Apr 10 '21 21:04

v.p.


People also ask

What does Use_count return in C++?

std::shared_ptr<T>::use_count Returns the number of different shared_ptr instances (this included) managing the current object. If there is no managed object, ​0​ is returned.

Is shared_ptr reference counting?

The shared reference counter counts the number of owners. Copying a std::shared_ptr increases the reference count by one. Destroying a std::shared_ptr decreases the reference count by one. If the reference count becomes zero, the resource will automatically be released.

Is shared_ptr slow?

shared_ptr are noticeably slower than raw pointers. That's why they should only be used if you actually need shared ownership semantics. Otherwise, there are several other smart pointer types available. scoped_ptr and auto_ptr (C++03) or unique_ptr (C++0x) both have their uses.


2 Answers

The problem is the temporary initializer_list<shared_ptr> keeps a copy of the elements, and it lives until the end of the full-expression (the ;).

There isn't much you can do, an initializer_list always stores its elements by copy.

As a workaround, you can construct the vector beforehand:

std::vector<std::shared_ptr<int>> list{std::move(sharedTest), std::move(anotherSharedTest)};
testFunc(list);

Should print 1 1.

like image 171
rustyx Avatar answered Oct 19 '22 00:10

rustyx


According to this answer, std::initializer_list only allows const access to its elements. This means that the std::vector constructor needs to copy all elements from the list (because move is non-const).

like image 1
pschill Avatar answered Oct 19 '22 01:10

pschill