3

From en.cppreference.com

Typical uses of std::unique_ptr include:

  • providing exception safety to classes and functions that handle objects with dynamic lifetime, by guaranteeing deletion on both normal exit and exit through exception

  • passing ownership of uniquely-owned objects with dynamic lifetime into functions

  • acquiring ownership of uniquely-owned objects with dynamic lifetime from functions

  • as the element type in move-aware containers, such as std::vector, which hold pointers to dynamically-allocated objects (e.g. if polymorphic behavior is desired)

I am interested in the first point.

It is not mentioned for shared_ptr in cppreference.com. I am not able to find a scenario where the shared_ptr doesn't get deleted when an exception is thrown. Could someone please explain if there exists such possibilities ?

Community
  • 1
  • 1
Sreeraj Chundayil
  • 5,548
  • 3
  • 29
  • 68
  • @user4581301: But it is not a problem related to exception , right? even if there is no exception this can lead to a problem ? – Sreeraj Chundayil Feb 23 '16 at 18:54
  • No, but it's an example of why you cannot guarantee deletion period. – user4581301 Feb 23 '16 at 18:57
  • The shared pointer is not even constructed if the allocation or the construction of the shared object throws an exception. If memory has been allocated, that memory is released. (Please do not ask me to prove it with quotes from the standard) –  Feb 23 '16 at 19:15

2 Answers2

4

Let's look into example as how std::unique_ptr can be used for providing exception safety:

someclass *ptr = new someclass;
...
delete ptr; // in case of exception we have problem

so instead we should use:

std::unique_ptr<someclass> ptr = std::make_unique<someclass>();
... // no problem

simple, safe and no overhead.

So can shared_ptr be used same way to provide exception safety? Yes it can. But it should not, as it is designed for different purpose and would have unnecessary overhead. So it is not mentioned as a tool for such cases, but it does not mean it would not delete owned object if it is the only owner.

Slava
  • 43,454
  • 1
  • 47
  • 90
  • Where that overhead happens? Because make_shared<> is available right? Since all shared_ptr are inside stacks, when stack unwinding happens, all have to go out of scope, isn't it? – Sreeraj Chundayil Feb 23 '16 at 18:57
  • 2
    @InQusitive atomic (potentionally blocking) increment/decrement of shared counter(s). Memory overhead for control block. Accessing type-erased deleter. – Revolver_Ocelot Feb 23 '16 at 18:59
  • 1
    @InQusitive, `shared_ptr` is **way** more complicated object than `unique_ptr`, with more and heavier operations in it's constructor and destructor. For example, `shared_ptr` does **atomic** decrement in it's destructor - a lengthy operation - while unique_ptr simply calls deleter. – SergeyA Feb 23 '16 at 19:00
  • 1
    @InQusitive it seems that you do not actually understand how `shared_ptr` work. Aside from `shared_ptr` object (which contains one or two pointers) there is a control block which (bar custom allocators) is allocated on heap and shared by all instances of `shared_ptr` to same object (and created with aliacing constructor). It is needed to actually determine when object is safe to delete. Operations on that block is what makes `shared_ptr` costly in terms of perfomance – Revolver_Ocelot Feb 23 '16 at 19:11
  • @Revolver_Ocelot: Some links with the detailed explanation of control block? – Sreeraj Chundayil Feb 23 '16 at 19:19
  • 1
    @InQusitive read here http://stackoverflow.com/questions/2802953/how-do-shared-pointers-work – Slava Feb 23 '16 at 19:19
  • @InQusitive and in [cppreference article](http://en.cppreference.com/w/cpp/memory/shared_ptr) under __implementation notes__ – Revolver_Ocelot Feb 23 '16 at 19:22
3

As the name suggest a std::shared_ptr shares it's pointer. If an exception is thrown and the scope is left the shared pointer gets destroyed but if there is another std::shared_ptr somewhere that is a copy then the underlying pointer is not deleted but instead just the reference counter is decremented.

This is why they cannot guarantee the deletion will happen. Since std::unique_ptr is unique the guarantee can be given as we know it is the only one holding onto the pointer.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • But each shared_ptr will go out of scope and it will decrement the count , right? – Sreeraj Chundayil Feb 23 '16 at 18:49
  • Since shared_ptr is inside stack, when stack unwinding happens, all have to go out of scope, isn't it? – Sreeraj Chundayil Feb 23 '16 at 18:53
  • @InQusitive yes, it would decrement count. `shared_ptr` is exception safe in same sense `unique_ptr` is. It is just not intended to be used __just__ to provide exception safety. – Revolver_Ocelot Feb 23 '16 at 18:57
  • @InQusitive, shared_ptr is usually copied more often than created, this is it's scenario. Exception safety will only apply to initial creation. – SergeyA Feb 23 '16 at 18:58
  • 1
    @InQusitive It's not necessarily in the stack, it can be anywhere, like any object in C++. – Emil Laine Feb 23 '16 at 18:59
  • @InQusitive It depends on where things happen. If you have a shared pointer way up in the stack and the exception happens at a level that will never get that high then the pointer will not be deleted. The stack object is but the underlying pointer still lives higher up on the stack. With a unique pointer this cannot happen. – NathanOliver Feb 23 '16 at 19:00
  • @zenith: Could you please give me a sample code for creating a smart_pointer on heap? – Sreeraj Chundayil Feb 23 '16 at 19:06
  • @zenith: ok, i've never seen or used such example :) – Sreeraj Chundayil Feb 23 '16 at 19:08
  • @zenith, yet it could have it's use (not exactly like that, but similar) – SergeyA Feb 23 '16 at 21:15