38

scoped_ptr is not copy able and is being deleted out of the scope. So it is kind of restricted shared_ptr. So seems besides the cases when you really need to restrict the copy operation shared_ptr is better to use. Because sometimes you don’t know you need to create a copy of your object or no. So the question is: besides the cases mentioned above, could we consider that shared_ptr is better (or recommended) to use instead of scoped_ptr. Does scoped_ptr work much faster from shared_ptr, or does it have any advantages?

Thanks!

user
  • 5,335
  • 7
  • 47
  • 63
Narek
  • 38,779
  • 79
  • 233
  • 389

5 Answers5

72

shared_ptr is more heavyweight than scoped_ptr. It needs to allocate and free a reference count object as well as the managed object, and to handle thread-safe reference counting - on one platform I worked on, this was a significant overhead.

My advice (in general) is to use the simplest object that meets your needs. If you need reference-counted sharing, use shared_ptr; if you just need automatic deletion once you've finished with a single reference, use scoped_ptr.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • 16
    Mike, I couldn't agree more. I always advise people to start with `boost::scoped_ptr`. If you need transfer of ownership semantics (maintaining single ownership) then "upgrade" to `std::auto_ptr`. If you need shared ownership only then do you use `boost::shared_ptr`. Also, the `Boost.ptr_container` library is a nice alternative to containers of boost::shared_ptr when the elements don't really need to be shared. – David Joyner Nov 20 '09 at 14:28
  • 2
    As an aside: if you do need shared pointers, you can get rid of the extra allocations by allocating objects using `make_shared` or `allocate_shared` instead of `new`. – Mike Seymour Nov 20 '09 at 14:31
  • 17
    @David: I mostly agreed, but I'd skip `auto_ptr` entirely. It can't be used safely in standard containers, so it's likely to spring a few nasty surprises if you're not *really* careful. – jalf Nov 20 '09 at 15:03
  • 1
    Agreed, especially as auto_ptr is deprecated as of c++11, it shouldn't be recommended, instead I'd mention unique_ptr. – Kit10 Jun 09 '16 at 12:51
16

Performance - shared_ptr has more functionality, but also requires an additional allocation (it's also larger, but that rarely matters).

[edit] The second allocation can be avoided by using make_shared, but then weak_ptr will hold the entire entire allocation even after the object is destroyed, which may be a problem for large objects.

Expresison of Intent using scoped_ptr you state more explicitly what you want to do. (In case you wonder - that's a good thing :) ). If you do this correctly, shared_ptr will also indicate "this object is intended to live beyond this scope"

peterchen
  • 40,917
  • 20
  • 104
  • 186
  • 3
    +1 for expression of intent. In that vein, `scoped_ptr` is very clear as is `shared_ptr`. Likewise, use of `std::auto_ptr` should signal that you're willing to transfer ownership of the object at some point. – David Joyner Nov 20 '09 at 14:30
6

Their intended purpose is different, so, in many cases "shared_ptr vs scoped_ptr" is not a question at all. Sure, you can use a shared_ptr when all you need is a scoped_ptr. But what's the point? shared_ptr has likely a slightly bigger overhead with all the reference counting involved.

sellibitze
  • 27,611
  • 3
  • 75
  • 95
3

scoped_ptr works much faster from shared_ptr. It's right. shared_ptr always allocate memory using your allocator or default allocator.

Alexey Malistov
  • 26,407
  • 13
  • 68
  • 88
1

Scoped_ptr has little in common with shared_ptr, weak_ptr, or unique_ptr because it is only doing very special case of "reference counting". It isn't something you will need very often in well-designed code, but it is a good tool to have available.

Basically, a scoped_ptr isn't a reference-counted thing at all. Rather, it is an object you create on the stack (within the local scope) so that you can do something like this:

  //Some enclosing scope- anything set off by "{}" or even a function:
   {
       scoped_ptr<MyObject> ptr = new MyObject( parameters...);
   } // When we hit this closing brace, "ptr" will delete the "MyObject" inside.

You tend to see this pattern more with mutexes and other synchronization primatives- I can declare an "AutoLock" that will lock the mutex passed into it, then unlock it when it deletes to turn the whole "{}" scope into a critical section.

Also notice that a 'scoped_ptr' only ever makes sense when you can't just do a plain-old stack allocation like "MyObject obj(params..)" for some reason. After all, what it is doing is letting you use a heap-allocated object as if it was one on the stack. That tends to be a lot rarer a use case than the reference-counting of shared_ptr & its cousins.

Zack Yezek
  • 1,408
  • 20
  • 7