Storing boost_shared pointers in a vector - Is it expensive - c++

I know that vectors tend to make a copy of all objects pushed into them. My question is whether it would make sense to store a pointer to a boost::shared_ptr in a vector rather than the shared ptr itself

The only 100% correct answer to any performance questions is "profile and see."
However, in this particular case, you should just keep the shared_ptrs in there directly (by value). The overhead of copying a shared pointer is low. And if your compiler supports moves, it will even be moved instead - although then you'd probably be using std::shared_ptr, right?
How would you do it to store just pointers in there, anyway? Allocate the shared_ptrs dynamically? How would you control their own ownership?

shared_ptr are meant to manage the life-time of raw pointers. Storing and accessing them thru containers is hardly an overhead. If you store a pointer to shared_ptr into a container then you would defeat the whole purpose of shared_ptr.

Why would you ask about "expensive"? Your first concern apart from correctness should be "is it safe". Your second concern should be "is it readable and maintainable". Cost only is in the top 5 of your concerns if you know (by profiling) that you are working in a performance sensitive area. And even then there's "safety first" in almost every case.
So:
don't use pointers to shared_ptr, because it's hard to get that safe and correct.
don't use pointers to shared_ptr, because it's brittle, hard to descipher and makes everyone wonder why you did that (maintainability)
don't use pointers to shared_ptr unless you really know that copying the shared_ptrs is a performance issue, and you know by profiling and you don't have other, safer, more maintainable and equally performant solutions
tl;dr don't use pointers to shared_ptr.

Related

What is the advantage of a unique_ptr over a shared_ptr

I'm currently learning about the unique_ptr and shared_ptr types in C++. The advantages of smart pointers over raw pointers are apparent, and there are lots of explanations why you should prefer them over raw pointers. What I'm struggling to understand is why you would ever specifically choose to use a unique_ptr over a shared_ptr?
As far as I can tell, from the programmers perspective (ignoring implementation) , a unique_ptrjust seems like a special-case version of a shared_ptr where the reference count is restricted to one. So if I create a shared_ptr and only ever create a single reference, then I basically have the utility of a unique_ptr (with the ability to use the shared part in the future).
So what advantage does a unique_ptr give you? I should admit that I approach this as a Java programmer and a shared_ptr seems pretty darn close to the way Java works.
a unique_ptr just seems like a special-case version of a shared_ptr where the reference count is restricted to one
This is not true, and is the crux of why you would use one or another. A shared_ptr is a reference counted pointer. In order for it to be thread safe it uses an atomic counter for the reference count. So that means for a shared_ptr you have the extra overhead of storing the reference counter, plus the execution overhead of checking/manipulating that counter in all the functions that affect it. This overhead can make a noticeable impact on performance
A unique_ptr, conversely, is a non reference counted pointer. It can get away without having a reference counter because it is not copyable. That means it is basically a zero cost abstraction for newing and deleteing a pointer.
So, if you never need to share ownership, or you can just move it from place to place, and you want self management, then you want a unique_ptr. This covers the vast majority of pointer use cases. When you truly need shared ownership then you can go ahead and use shared_ptr, but understand you suffer a performance penalty for that shared ownership.

Realloc creates dangling pointers?

I wrote some array code that allocates memory and each value in the array is a type. I then have another array that consists of in to the first array for references.
Both arrays can grow. It uses realloc. Because the 2nd array contains pointers in to the first, they are surely not updated when the first array changes(I don't do it manually and there is no GC). Surely all the pointers in the 2nd array are invalid! (they point to memory that was free'ed by realloc).
This is the case right?
This seems like it would make persistent pointers to blocks of memory that may move very dangerous?
What is the standard solution? Don't use "global" pointers? Using pointers to pointers to pointers? I think I could make the 2nd array use **'s and could probably get things to work.
In a MT environment, things are even worse. Local pointers access may be moved in the middle, then the memory changed, and the local pointer is now wrong. (Which, of course might be solved by preventing the moves by lock, etc...)
Go with functional programming?
Yes, the realloc can invalidate your references. If there is no continuous space for relocating your array will be moved.
Consider using a container as the std::deque.
1) This is the case right?
Yes.
2) This seems like it would make persistent pointers to blocks of memory that may move very dangerous?
Yes.
3) What is the standard solution?
You design your application such that the life-times of your objects is well defined so that you do not refer to them after they are no longer required.
4) In a MT environment, things are even worse. Local pointers access may be moved in the middle, then the memory changed, and the local pointer is now wrong. (Which, of course might be solved by preventing the moves by lock, etc...)
Obviously you should never use a pointer that no-longer pointers to its resource. Managing shared resources in a MT environment is non trivial and there are a whole bunch of tools and techniques to achieve it.
5) Go with functional programming?
It is always advisable to avoid pointers if you can.
Without a specific problem it is hard to give a specific solution. But in order to achieve "not pointing at disappeared resources" we have various tools to employ. We have smart pointers, we have containers and we have value semantics. We need to understand how to use all of those but also we need to design with object lifetime in mind as a major consideration.
Object life-time should always be an important factor. However some languages (like Java for instance) mitigate against bad-design by providing a "safer" environment. C++, on the other hand, is rather less forgiving. However it does have a whole bunch of sophisticated tools for the task. That means a steeper learning curve but more efficiency and better control.

Raw Pointer Management in C++

I have a piece of performance critical code. The class and objects are fairly large, hence, it would be stored as pointers in the STL container. Problems arise when the pointers to objects need to be stored in multiple different containers based on some logic. It is very messy in handling the ownership of the object as I couldn't isolate the ownership of the object to a single containers(which I could just delete from the single container). Other than using smart pointer (since it is performance critical and smart pointer might affects the performance), what could I do?
Thanks.
You are asking for impossible - from one point, you are asking for exceptional performance, such that smart pointers you claim cannot provide, and you also happen to ask for safety and tidiness. Well, one comes at the cost of another, actually. You could, of course try to write your own shared pointer, which would be more lightweight than boost's, but still provide the basic functionality. Incidentally, have you actually tried boost::shared_ptr? Did it actually slow down the performance?
Your question is very awkward: you ask for performance with a messy logic ?
shared_ptr have incredible performance, really, and though you can get better it is probably your best choice: it works.
You could look up another Boost smart pointer though: boost::intrusive_ptr.
This is done at the cost of foregoing: weak_ptr and in exchange allows to have a single memory allocation for both the counter and the object. Packing up the two yields a SMALL increase in performance.
If you do not have cyclic reference, try and check it out, it might be what you were looking for.
Intrusive smart pointers are typically more efficient than normal smart pointers, yet easier than dumb pointers. For instance, check out boost::intrusive_ptr<T>
If the objects don't refer to one another, manual reference counting might be worth trying. There would be more cost when adding to or removing from a list, but no overhead to the actual object access. (This can be painful to diagnose when you get it wrong, so I recommend being careful to get it right.)
If there is dead time between operations, consider a sort of garbage collect. Maintain the list of all objects (an intrusive list would probably do). When you have time to spare, cross-reference this against the other lists; any objects that aren't in a list can get deleted. You don't need an extra array to do this (just a global counter and a last-seen counter on each object) so it could be reasonably efficient.
Another option would be to use a smart pointer that provides access to the underlying pointer. If you're trying to avoid the overhead of calling an overloaded operator-> a lot then this might be worth trying. Store the smart pointers in the lists (this does the lifetime management for you) and then when running through the objects you can retrieve the raw pointer for each and operate using that (so you don't incur the overhead of any overloaded operator-> etc.). For example:
std::vector<smart_ptr<T> > objects;
if(!objects.empty()) {
smart_ptr<T> *objects_raw=&objects[0];
for(size_t n=objects.size(),i=0;i<n;++i) {
T *object=objects_raw[i].get_ptr();
// do stuff
}
}
This is the sort of approach I prefer personally. Long-term storage gets a smart pointer, short-term storage gets a plain pointer. The object lifetimes are easy to manage, and you don't fall foul of 1,000,000 tiny overheads (more important for keeping the debug build runnable than it is for the release build, but it can easily add to wasted time nonetheless).

I can't use std::vector of auto_ptr - should i use shared_ptr?

I don't really need to share the objects, but i do want to make sure no memory leakage occurs.
Is it correct to use shared_ptr in this case?
If you are using boost, boost::ptr_vector might be better suited for your needs.
If not, then you can either use shared_ptr as you suggested or manually delete the elements of the vector once you are done with them.
From maintenance point of view, shared_ptr would be the preferred solution. Note, however, that shared_ptr can bring some performance penalties, which may or may not be significant for your application.
If low-level performance/ memory usage are not critical requirements (ie 97% of all cases) then just go with shared_ptr. It's straightforward and well understood.
If you really want to keep things tight and/ or express the ownership intention more precisely then boost::ptr_vector might be better - but if your class doesn't manage any other memory then just manually deleting in your destructor is not as big a sin as we're sometimes led to believe ;-) I'm a big RAII proponent, but still do this from time to time.
It is a bit of an overkill, but there isn't a much better smart pointer for that. You might also consider boost's pointer containers.
In C++0x you'd be able to store std::unique_ptr in containers, which is closer to your needs.
You can also use Boost.PointerContainer. Using a shared_ptr expresses shared ownership. Now if you are sure, that your objects are bound to the lifetime of the container, then a PointerContainer is the better option design-wise (is that even a word?).

Are there any reasons not to use Boost::shared_ptrs?

I've asked a couple questions (here and here) about memory management, and invariably someone suggests that I use boost::shared_ptrs.
Given how useful they seem to be, I'm seriously considering switching over my entire application to use boost::shared_ptrs.
However, before I jump in with both feet and do this, I wanted to ask -- Has anyone had any bad experiences with boost::shared_ptrs? Is there some pitfall to using them that I need to watch out for?
Right now, they seem almost too good to be true - taking care of most of my garbage collection concerns automatically. What's the downside?
The downside is they're not free. You especially shouldn't use shared_ptr/shared_array when scoped_ptr/scoped_array (or plain old stack allocation) will do. You'll need to manually break cycles with weak_ptr if you have any. The vector question you link to is one case where I might reach for a shared_ptr, the second question I would not. Not copying is a premature optimization, especially if the string class does it for you already. If the string class is reference counted, it will also be able to implement COW properly, which can't really be done with the shared_ptr<string> approach. Using shared_ptr willy-nilly will also introduce "interface friction" with external libraries/apis.
Boost shared pointers or any other technique of memory management in C++ is not a panacea. There is no substitution for careful coding. If you dive into using boost::shared_ptr be aware of object ownership and avoid circular references. You are going to need to explicitly break cycles or use boost::weak_ptr where necessary.
Also be careful to always use boost::shared_ptr for an instance from the moment it is allocated. That way you are sure you won't have dangling references. One way you can ensure that is to use factory methods that return your newly created object in a shared_ptr.
typedef boost::shared_ptr<Widget> WidgetPtr;
WidgetPtr myWidget = Widget::Create();
I use shared_ptr's often.
Since Shared_ptr's are copied by-value, you can incur the cost of copying both the pointer value and a reference count, but if boost::intrusive_ptr is used, the reference count must be added to your class, and there is no additional overhead above that of using a raw pointer.
However, in my experience, more than 99% of the time, the overhead of copying boost::shared_ptr instances throughout your code is insignificant. Usually, as C. A. R. Hoare noted, premature optimization is pointless - most of the time other code will use significantly more time than the time to copy small objects. Your mileage may vary. If profiling show the copying is an issue, you can switch to intrusive pointers.
As already noted above, cycles must be broken by using a weak_ptr, or there will be a memory leak. This will happen with data structures such as some graphs, but if, for example, you are making a tree structure where the leaves never point backwards, you can just use shared_pointers for nodes of the tree without any issues.
Using shared_ptr's properly greatly simplifies code, makes it easier to read, and easier to maintain. In many cases using them is the right choice.
Of course, as already mentioned, in some cases, using scoped_ptr (or scoped_array) is the right choice. If the pointee isn't being shared, don't use shared pointers!
Finally, the most recent C++ standard provides the std::tr1::shared_ptr template, which is now on most platforms, although I don't think there is an intrusive pointer type for tr1 (or rather, there might be, but I have not heard of it myself).
Dynamic memory overhead (i.e., extra allocations) plus all the overhead associated with reference counted smart pointers.