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!
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.
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.
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.
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
.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With