Reputation: 3558
I have some questions about smart pointers implemented in boost library. Is the only diffrence between shared_ptr and scoped_ptr that scoped_ptr doesn't have copy constructor and shared_ptr has it? Should i use then scoped_ptr instead of shared_ptr always when object doesn't call copy constructor? I also doesn't understand idea of shared/scoped array. Can't I just use std::vector instead of it?
Upvotes: 1
Views: 3891
Reputation: 52149
Is the only diffrence between shared_ptr and scoped_ptr that scoped_ptr doesn't have copy constructor and shared_ptr has it?
The difference is more fundamental than that; it has to do with how the smart pointers own the object it points to. What makes smart pointers different from dumb pointers is that the concept of ownership is a core component of their function. The ownership semantics is what differentiates the different kinds of smart pointers.
Because smart pointers "own" the thing they point to, they can do useful things like deleting objects when the smart pointers go away (this is made possible using only the rules of the language; no compiler magic is needed). This way, memory management can be made almost automatic in C++ (despite claims to the contrary, there's very little manual memory management required in modern C++).
shared_ptr
implements reference-counting
semantics for
memory management. Multiple shared_ptr
s can own a single object. A
shared_ptr
going away does not necessarily delete the object it
points to because there may be another shared_ptr
owning the
object. The last shared_ptr
that owns an object and goes away will
delete the object it owns.
scoped_ptr
implements exclusive-ownership semantics. Only one
scoped_ptr
can own any one object. When a scoped_ptr
goes away,
it will always delete the object it owns (because there's only one
owner). It's typically used as a lightweight RAII mechanism for
objects allocated on the free store.
The array versions (shared_array
and scoped_array
) have essentially the same semantics, but are designed specifically for arrays e.g. they use delete[]
instead of delete
, implements the array subscript operator, etc.
shared_ptr
and shared_array
also allows you to specify a custom deleter, if the default delete
behavior is not appropriate for the object. scoped_ptr
and scoped_array
do not have that ability, since they are quite lightweight compared to shared_ptr
and shared_array
.
In C++11, the newest and current version of C++, there's also a unique_ptr
, which is just like scoped_ptr
except that you can transfer the ownership of an object to another unique_ptr
. In C++03, an older but more widely supported version of C++, there's auto_ptr
which is equivalent to unique_ptr
except it was easy to use it in an unsafe manner by accident (which is why it is deprecated in C++11).
Should i use then scoped_ptr instead of shared_ptr always when object doesn't call copy constructor?
Which one you choose doesn't depend on the presence of the copy-constructor, since shared_ptr
and scoped_ptr
does not require the object to be copy-constructible. You pick the one depending on the required ownership semantics. If the object will have multiple owners, you use shared_ptr
. If the object will only have one owner and the object's existence lasts only within a scope, use scoped_ptr
(hence the name scoped_ptr
).
I also doesn't understand idea of shared/scoped array. Can't I just use std::vector instead of it?
std::vector
does not implement reference-counting semantics like shared_array
does. std::vector
is more like scoped_array
, but can be copied. When you copy a std::vector
, you also copy all of the elements it contains. That's not the case for scoped_array
. std::vector
also has functions that allow you to manipulate and examine its contents (e.g. push_back
, insert
, erase
, etc.), but is much more heavyweight than scoped_array
.
Upvotes: 10
Reputation: 53289
shared_ptr
is very different from scoped_ptr
. scoped_ptr
(which is now standardized in C++11 as std::unique_ptr
) is simply a RAII-style smart pointer which takes ownership of a resource and then deallocates the owned resource when the pointer goes out of scope.
A shared_ptr
however, may share ownership of the resource with other instances of shared_ptr. The resource stays alive as long as one or more shared_ptr
instances own it. This is an automatic memory-management technique, (a form of garbage-collection) known as reference counting. It basically provides the same effect as more advanced garbage collection algorithms, except unlike other garbage collection techniques, it doesn't handle circular references.
As for using std::vector
versus boost::scoped_array
, yeah - scoped_array
doesn't really offer much of an advantage. However, boost::shared_array
offers reference counting semantics, just like shared_ptr
.
Upvotes: 1
Reputation: 2015
I'd say you're thinking about it the wrong way. The question isn't whether you do call the copy constructor -- it's whether you need to call the copy constructor. In other words, you should be deciding whether to use shared_ptr or scoped_ptr not based on reading your code but based on thinking about object ownership and what objects' lifetimes should be.
Say you have an object that you want to create on the heap, not on the stack, for whatever reason (maybe it's too big to be on the stack, maybe you might want to replace it with a different object at some point, maybe you want it to be initialized late) but its lifetime should never be longer than its containing scope. A common example of this is instance variables in a class: they should often be deleted when the object they are in is deleted. Then, you should use scoped_ptr.
But sometimes you don't know when an object will be safe to delete in advance. For instance, consider an object in a lookup table. You want to return it in response to lookups, but what happens when it's deleted -- could someone still be using the object who looked it up previously? In cases like this, you can use shared_ptr, which shares the objects ownership so that it only gets deleted when nobody has a copy of the pointer anymore.
So why does anyone ever use scoped_ptr instead of shared_ptr? First of all, knowing when the destructor gets called is one of the big advantages of non-memory-managed languages like C++. Maybe the destructor is expensive, or maybe it frees a resource; it's nice to know when these things happen. Also, with shared_ptr, there's the potential for memory leaks if you create a circular reference by accident.
In general, almost every pointer you have should be "owned" -- there should be a single place in your code that news and deletes it. scoped_ptr is great for this; when you want an owned object to be passed around to non-owners you can use a bare pointer. But if you absolutely need an object's ownership to be shared, use shared_ptr -- as long as you're careful to use it correctly!
As for scoped/shared arrays, you can certainly use std::vector, but arrays are cheaper and sometimes people want the performance benefit.
Upvotes: 1
Reputation: 4357
If you allocate memory, you can put the newly created pointer in a scoped pointer, so that IF the malloc/noew fails, the memory will be freed. This is how I usally uses it, or if it's an object that needs to be allocated on the heap, but that I want to treat it as a stack object in terms of that it will only be alive until the end of the scope.
The shared pointer is if you want to pass the pointer around and allow the object to have multiple owners. Then none of the owners needs to take responibility of the object and they can all just stop using it and be sure that it will be freed correclty. (you don't wanna free an object that you know is used by someone else)
Upvotes: 1
Reputation: 29519
Yes. scoped_ptr
does not allow for copies while shared_ptr
does. But this "simple" difference makes a world of impact on both the implementation and the usage of the smart pointer.
scoped_ptr
is faster and lighter than shared_ptr
because no reference counting is involved. shared_ptr
will count the number of assignments and not delete the object until all references have expired/gone out of scope.
Now your question regarding vectors implies that you're actually not familiar with the the concept of dynamic allocation and the difference between that and static allocation on the static. You really should look into reading a primer on C(++) and look into the reasons for dynamic allocation and when you need it.
A vector stores a list of objects. A XXX_ptr
stores a pointer to a (single) dynamically-allocated object. Apples and oranges.
Upvotes: 1