0

I'm trying to get my head around shared pointers at the moment and how they work. I would be really grateful for any advice you could give on the below.

Please could you advise on:

  • When to use std::move in make_shared

  • What the shared pointer points to if it is constructed using make_shared on an object which is constructed using emplace_back and some user input and that object then disappears from scope e.g. in a for loop I write,

vector_declared_outside_for_loop.emplace_back(std::make_shared(object(std::string user_input)))

, what happens to the shared_ptr in the for loop after the for loop ends?

  • If I now make a vector of pairs of the shared_ptrs from vector_declared_outside_for_loop and some other variable such as int number_input in a subsequent for loop eg.
std::vector<std::pair<shared_ptr<object>, int>> new_vector;

    for(int i{0}; i<.size(); ++i){

   new_vector.push_back(std::make_pair(shared_ptr<object> vector_declared_outside_for_loop [i], int connection_type));

   }

Do the shared_ptrs in new_vector point to anything? Or am I just pushing new_vector back?

2
  • Don't think of a shared_ptr as "pointing to" an object, think of it as being an object that can be shared. It behaves exactly like any other C++ object. make_shared<T>(arguments) is almost the same as shared_ptr<T>(new T(arguments)), but safer and ore efficient. Commented May 17, 2022 at 15:39
  • A minimal reproducible example might help explain your question Commented May 17, 2022 at 15:40

1 Answer 1

0
  • You use std::move whenever you have a named object that you no longer use. Just forget all you think you know about std::move and learn one simple rule: std::move means: I no longer need this (name object).
    So func1(std::move(func2(...))) makes no sense. The returned object has no name, there is no way for you to use it again. The compiler knows that and will already use move semantic without std::move. Saying I no longer need this is pointless because after the func1 call the temporary object no longer exists.

  • make_shared allocates a new object to point to and constructs it in place. But then when you emplace_back what you are emplacing is the shared_ptr, not the object it points to. So what happens is that shared_ptr is constructed in place inside the vector with a pointer to the object it alloctes and constructs.
    The shared_ptr in the for loop doesn't exist at all. That's the point of the emplace_back that it doesn't create a temporary object but constructs the object in-place inside the vector directly.

  • push_back normally takes an object and copies it into the vector. So you would create a temporary object, copy it and destroy the temporary. But the STL isn't stupid and covers this case too. If you push_back an object that can be moved then it is forwarded to emplace_back. So again the pair will be constructed directly in-place inside the vector.
    That leaves the vector_declared_outside_for_loop. Since it is an existing object it can't be constructed in-place. Since it is a named object it can not be moved. So the objects will be copied.
    For a shared_ptr that means the internal pointer will be copied and the reference count for the object will be incremented atomically. So at the end of the loop the shared_ptr will have a reference count of .size() + 1. Then at the end of the scope the original shared_ptr goes out of scope reducing the reference count by 1. The object used in the vector remains.

Sign up to request clarification or add additional context in comments.

4 Comments

In the third point, you mentioned the original shared_ptr goes out of scope. I am taking this to mean that the shared_ptr from vector_declared_outside_for_loop gets deleted. However, the shared_ptr in new_vector remains. If so, why does the shared_ptr from vector_declared_outside_for_loop get deleted? Thanks for answering my question!
The shared_ptr is a class like any other. If you declare a shared_ptr in a block of code then it gets destroyed at the end of the scope, at the }. That's just like every other object. But the thing the shared_ptr points to only gets destroyed when all copies of a shared_ptr are destroyed. That's the semantic of the shared_ptr.
Thanks, is there a way for shared_ptr to not be destroyed here?
No. And you don't want it to. It's doing the right thing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.