This is a basic question, but I did not find a previous post about it. The title of the following question sounds like it might be the same question as mine, but the question it
I won't include the rationale behind your first sub-question of the difference between construction via make_shared or from a pointer, as this difference is highlighted in several different locations, including this excellent question.
However, I think it is constructive to distinguish between using reset and operator=. The former relinquishes ownership of the resource managed by the shared_ptr, either by destroying it if the shared_ptr happened to be the sole owner, or by decrementing the reference count. The latter implies shared ownership with another shared_ptr (unless you're move constructing).
As I mentioned in the comments, it's important that the pointer passed in to reset not be owned by another shared or unique pointer, because it would yield undefined behavior upon the destruction of the two independent managers - they both would attempt to delete the resource.
One use case of reset could be lazy initialization of a shared resource. You only want the shared_ptr to manage some resource, memory for example, if you really need it. Doing an outright allocation, such as:
std::shared_ptr shared_resource(new resource(/*construct a resource*/));
might be wasteful if its never actually needed. To do this with lazy initialization, something like this may apply:
std::shared_ptr shared_resource;
void use_resource()
{
if(!shared_resource)
{
shared_resource.reset(new resource(...));
}
shared_resource->do_foo();
}
Using reset in this case is more concise than doing a swap or assigning to a temporary shared_ptr.