Reason for using smart pointers with a container - c++

Simply written I would like to ask "what is a good reason to use smart pointers?"
for ex std::unique_ptr
However, I am not asking for reasons to use smart pointers over regular (dumb) pointers. I think every body knows that or a quick search can find the reason.
What I am asking is a comparison of these two cases:
Given a class (or a struct) named MyObject use
std:queue<std::unique_ptr<MyObject>>queue;
rather than
std:queue<MyObject> queue;
(it can be any container, not necessarily a queue)
Why should someone use option 1 rather than 2?

That is actually a good question.
There are a few reasons I can think of:
Polymorphism works only with references and pointers, not with value types. So if you want to hold derived objects in a container you can't have std::queue<MyObject>. One options is unique_ptr, another is reference_wrapper
the contained objects are referenced (*) from outside of the container. Depending on the container, the elements it holds can move, invalidating previous references to it. For instance std::vector::insert or the move of the container itself. In this case std::unique_ptr<MyObject> assures that the reference is valid, regardless of what the container does with it (ofc, as long as the unique_ptr is alive).
In the following example in Objects you can add a bunch of objects in a queue. However two of those objects can be special and you can access those two at any time.
struct MyObject { MyObject(int); };
struct Objects
{
std::queue<std::unique_ptr<MyObject>> all_objects_;
MyObject* special_object_ = nullptr;
MyObject* secondary_special_object_ = nullptr;
void AddObject(int i)
{
all_objects_.emplace(std::make_unique<MyObject>(i));
}
void AddSpecialObject(int i)
{
auto& emplaced = all_objects_.emplace(std::make_unique<MyObject>(i));
special_object_ = emplaced.get();
}
void AddSecondarySpecialObject(int i)
{
auto& emplaced = all_objects_.emplace(std::make_unique<MyObject>(i));
secondary_special_object_ = emplaced.get();
}
};
(*) I use "reference" here with its english meaning, not the C++ type. Any way to refer to an object (e.g. via a raw pointer)

Usecase: You want to store something in a std::vector with constant indices, while at the same time being able to remove objects from that vector.
If you use pointers, you can delete a pointed to object and set vector[i] = nullptr, (and also check for it later) which is something you cannot do when storing objects themselves. If you'd store Objects you would have to keep the instance in the vector and use a flag bool valid or something, because if you'd delete an object from a vector all indices after that object's index change by -1.
Note: As mentioned in a comment to this answer, the same can be archieved using std::optional, if you have access to C++17 or later.

The first declaration generates a container with pointer elements and the second one generates pure objects.
Here are some benefits of using pointers over objects:
They allow you to create dynamically sized data structures.
They allow you to manipulate memory directly (such as when packing or
unpacking data from hardware devices.)
They allow object references(function or data objects)
They allow you to manipulate an object(through an API) without needing to know the details of the object(other than the API.)
(raw) pointers are usually well matched to CPU registers, which makes dereferencing a value via a pointer efficient. (C++ “smart” pointers are more complicated data objects.)
Also, polymorphism is considered as one of the important features of Object-Oriented Programming.
In C++ polymorphism is mainly divided into two types:
Compile-time Polymorphism
This type of polymorphism is achieved by function overloading or operator overloading.
Runtime Polymorphism
This type of polymorphism is achieved by Function Overriding which if we want to use the base class to use these functions, it is necessary to use pointers instead of objects.

Related

Array: Storing Objects or References

As a Java developer I have the following C++ question.
If I have objects of type A and I want to store a collection of them in an array,
then should I just store pointers to the objects or is it better to store the object itself?
In my opinion it is better to store pointers because:
1) One can easily remove an object, by setting its pointer to null
2) One saves space.
Pointers or just the objects?
You can't put references in an array in C++. You can make an array of pointers, but I'd still prefer a container and of actual objects rather than pointers because:
No chance to leak, exception safety is easier to deal with.
It isn't less space - if you store an array of pointers you need the memory for the object plus the memory for a pointer.
The only times I'd advocate putting pointers (or smart pointers would be better) in a container (or array if you must) is when your object isn't copy construable and assignable (a requirement for containers, pointers always meet this) or you need them to be polymorphic. E.g.
#include <vector>
struct foo {
virtual void it() {}
};
struct bar : public foo {
int a;
virtual void it() {}
};
int main() {
std::vector<foo> v;
v.push_back(bar()); // not doing what you expected! (the temporary bar gets "made into" a foo before storing as a foo and your vector doesn't get a bar added)
std::vector<foo*> v2;
v2.push_back(new bar()); // Fine
}
If you want to go down this road boost pointer containers might be of interest because they do all of the hard work for you.
Removing from arrays or containers.
Assigning NULL doesn't cause there to be any less pointers in your container/array, (it doesn't handle the delete either), the size remains the same but there are now pointers you can't legally dereference. This makes the rest of your code more complex in the form of extra if statements and prohibits things like:
// need to go out of our way to make sure there's no NULL here
std::for_each(v2.begin(),v2.end(), std::mem_fun(&foo::it));
I really dislike the idea of allowing NULLs in sequences of pointers in general because you quickly end up burying all the real work in a sequence of conditional statements. The alternative is that std::vector provides an erase method that takes an iterator so you can write:
v2.erase(v2.begin());
to remove the first or v2.begin()+1 for the second. There's no easy "erase the nth element" method though on std::vector because of the time complexity - if you're doing lots of erasing then there are other containers which might be more appropriate.
For an array you can simulate erasing with:
#include <utility>
#include <iterator>
#include <algorithm>
#include <iostream>
int main() {
int arr[] = {1,2,3,4};
int len = sizeof(arr)/sizeof(*arr);
std::copy(arr, arr+len, std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
// remove 2nd element, without preserving order:
std::swap(arr[1], arr[len-1]);
len -= 1;
std::copy(arr, arr+len, std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
// and again, first element:
std::swap(arr[0], arr[len-1]);
len -= 1;
std::copy(arr, arr+len, std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
}
preserving the order requires a series of shuffles instead of a single swap, which nicely illustrates the complexity of erasing that std::vector faces. Of course by doing this you've just reinvented a pretty big wheel a whole lot less usefully and flexibly than a standard library container would do for you for free!
It sounds like you are confusing references with pointers. C++ has 3 common ways of representing object handles
References
Pointers
Values
Coming from Java the most analogous way is to do so with a pointer. This is likely what you are trying to do here.
How they are stored though has some pretty fundamental effects on their behaviors. When you store as a value you are often dealing with copies of the values. Where pointers are dealing with one object with multiple references. Giving a flat answer of one is better than the other is not really possible without a bit more context on what these objects do
It completely depends on what you want to do... but you're misguided in some ways.
Things you should know are:
You can't set a reference to NULL in C++, though you can set a pointer to NULL.
A reference can only be made to an existing object - it must start initialized as such.
A reference cannot be changed (though the referenced value can be).
You wouldn't save space, in fact you would use more since you're using an object and a reference. If you need to reference the same object multiple times then you save space, but you might as well use a pointer - it's more flexible in MOST (read: not all) scenarios.
A last important one: STL containers (vector, list, etc) have COPY semantics - they cannot work with references. They can work with pointers, but it gets complicated, so for now you should always use copyable objects in those containers and accept that they will be copied, like it or not. The STL is designed to be efficient and safe with copy semantics.
Hope that helps! :)
PS (EDIT): You can use some new features in BOOST/TR1 (google them), and make a container/array of shared_ptr (reference counting smart pointers) which will give you a similar feel to Java's references and garbage collection. There's a flurry of differences but you'll have to read about it yourself - they are a great feature of the new standard.
You should always store objects when possible; that way, the container will manage the objects' lifetimes for you.
Occasionally, you will need to store pointers; most commonly, pointers to a base class where the objects themselves will be of different types. In that case, you need to be careful to manage the lifetime of the objects yourself; ensuring that they are not destroyed while in the container, but that they are destroyed once they are no longer needed.
Unlike Java, setting a pointer to null does not deallocate the object pointed to; instead, you get a memory leak if there are no more pointers to the object. If the object was created using new, then delete must be called at some point. Your best options here are to store smart pointers (shared_ptr, or perhaps unique_ptr if available), or to use Boost's pointer containers.
You can't store references in a container. You could store (naked) pointers instead, but that's prone to errors and is therefore frowned upon.
Thus, the real choice is between storing objects and smart pointers to objects. Both have their uses. My recommendation would be to go with storing objects by value unless the particular situation demands otherwise. This could happen:
if you need to NULL out the object without removing it from the
container;
if you need to store pointers to the same object in
multiple containers;
if you need to treat elements of the container
polymorphically.
One reason to not do it is to save space, since storing elements by value is likely to be more space-efficient.
To add to the answer of aix:
If you want to store polymorphic objects, you must use smart pointers because the containers make a copy, and for derived types only copy the base part (at least the standard ones, I think boost has some containers which work differently). Therefore you'll lose any polymorphic behaviour (and any derived-class state) of your objects.

dynamic_cast reference to base class in stl container

Is it possible to store a bunch of objects by their base class in say an std::list without pointers. I would really like the objects to be held in the container, then retrieve a pointer to the object in the container and dynamic_cast it to correct derived class.
I have it working fine using pointers. Like (super simple version):
class IComponent
{
virtual ~Icomponent(){}
}
class PositionComponent: public IComponent
{
//...
float x, y;
}
std::list<IComponent*> CList;
//...
// fill the list
// put reference to object in pComponent
//...
PositionComponent* position = dynamic_cast<PositionComponent*>( pComponent)
position->x = 346452.235612;
But the memory management is a huge pain. My actual structure is a
map<enumValue, map<int, IComponent*> >
I get the feeling I can't use the objects themselves because when I add any derived component into the list the extra data will be cut off and leave me with the base class only. This didn't figure this until I tried static_cast instead and it crashed.
Can answer my original question and/or confirm my feelings on the matter. Thanks!
to minimize pain of manual memory management use smart pointers: std::unique_ptr if your compiler already supports it or boost::shared_ptr, but not std::auto_ptr that is not supposed to be used in containers
As you guessed, when you stored an object in a container by value, it gets sliced and the data is chopped off.
If you only need to store one data type (you only show one in your code), then you can make the container hold that type.
If not, you really are stuck using pointers. You can make the memory management much easier by using a smart pointer, or if appropriate, a boost ptr_container of some sort.
Further you might want to think if you need to spend one more iteration considering your design to provide an interface that doesn't require doing a dynamic_cast to get the original type back out again.
Is it possible to store a bunch of objects by their base class in say
an std::list without pointers.
This sentence seems to be contrdicted in C++ point of view IMO. Because STL container can only hold same type of object, if you put derived object into a base type container, it got sliced.
So the apparent normal solution is to use container to hold base type pointers like you did(u could use boost/std smart pointer for memory management)
If you really want to store different objects in one STL container, you may want to consider use boost::any.

Which kind of (auto) pointer to use?

I came accross several questions where answers state that using T* is never the best idea.
While I already make much use of RIIC, there is one particular point in my code, where I use T*. Reading about several auto-pointers, I couldn't find one where I'd say that I have a clear advantage from using it.
My scenario:
class MyClass
{
...
// This map is huge and only used by MyClass and
// and several objects that are only used by MyClass as well.
HashMap<string, Id> _hugeIdMap;
...
void doSomething()
{
MyMapper mapper;
// Here is what I pass. The reason I can't pass a const-ref is
// that the mapper may possibly assign new IDs for keys not yet in the map.
mapper.setIdMap(&_hugeIdMap);
mapper.map(...);
}
}
MyMapper now has a HashMap<...>* member, which - according to highly voted answers in questions on unrelated problems - never is a good idea (Altough the mapper will go out of scope before the instance of MyClass does and hence I do not consider it too much of a problem. There's no new in the mapper and no delete will be needed).
So what is the best alternative in this particular use-case?
Personally I think a raw pointer (or reference) is okay here. Smart pointers are concerned with managing the lifetime of the object pointed to, and in this case MyMapper isn't managing the lifetime of that object, MyClass is. You also shouldn't have a smart pointer pointing to an object that was not dynamically allocated (which the hash map isn't in this case).
Personally, I'd use something like the following:
class MyMapper
{
public:
MyMapper(HashMap<string, Id> &map)
: _map(map)
{
}
private:
HashMap<string, Id> &_map
};
Note that this will prevent MyMapper from having an assignment operator, and it can only work if it's acceptable to pass the HashMap in the constructor; if that is a problem, I'd make the member a pointer (though I'd still pass the argument as a reference, and do _map(&map) in the initializer list).
If it's possible for MyMapper or any other class using the hash map to outlive MyClass, then you'd have to start thinking about smart pointers. In that case, I would probably recommend std::shared_ptr, but you'd have to use it everywhere: _hugeIdMap would have to be a shared_ptr to a dynamically allocated value, not a regular non-pointer field.
Update:
Since you said that using a reference is not acceptable due to the project's coding standards, I would suggest just sticking with a raw pointer for the reasons mentioned above.
Naked pointers (normally referred to as raw pointers) are just fine when the object has no responsibility to delete the object. In the case of MyMapper then the pointer points to an object already owned by MyClass and is therefore absolutely fine to not delete it. The problem arises when you use raw pointers when you do intend for objects to be deleted through them, which is where problems lie. People only ask questions when they have problems, which is why you almost always see it only used in a problematic context, but raw pointers in a non-owning context is fine.
How about passing it into the constructor and keeping a reference (or const-reference) to it? That way your intent of not owning the object is made clear.
Passing auto-pointers or shared-pointers are mostly for communicating ownership.
shared pointers indicate it's shared
auto-pointers indicate it's the receivers responsibility
references indicate it's the senders responsibility
blank pointers indicate nothing.
About your coding style:
our coding standards have a convention that says never pass non-const references.
Whether you use the C++ reference mechanism or the C++ pointer mechanism, you're passing a (English-meaning) reference to the internal storage that will change. I think your coding standard is trying to tell you not to do that at all, not so much that you can't use references to do so but that you can do it in another way.

C++: Vector of objects vs. vector of pointers to new objects?

I am seeking to improve my C++ skills by writing a sample software renderer. It takes objects consisting of points in a 3d space and maps them to a 2d viewport and draws circles of varying size for each point in view. Which is better:
class World{
vector<ObjectBaseClass> object_list;
public:
void generate(){
object_list.clear();
object_list.push_back(DerivedClass1());
object_list.push_back(DerivedClass2());
or...
class World{
vector<ObjectBaseClass*> object_list;
public:
void generate(){
object_list.clear();
object_list.push_back(new DerivedClass1());
object_list.push_back(new DerivedClass2());
?? Would be using pointers in the 2nd example to create new objects defeat the point of using vectors, because vectors automatically call the DerivedClass destructors in the first example but not in the 2nd? Are pointers to new objects necessary when using vectors because they handle memory management themselves as long as you use their access methods? Now let's say I have another method in world:
void drawfrom(Viewport& view){
for (unsigned int i=0;i<object_list.size();++i){
object_list.at(i).draw(view);
}
}
When called this will run the draw method for every object in the world list. Let's say I want derived classes to be able to have their own versions of draw(). Would the list need to be of pointers then in order to use the method selector (->) ?
Since you are explicitly stating you want to improve your C++, I am going to recommend you start using Boost. This can help you with your problem in three different ways:
Using a shared_ptr
Using a shared_ptr could declare your vector like this:
std::vector< boost::shared_ptr< ObjectBase > > object_list;
And use it like this:
typedef std::vector< boost::shared_ptr< ObjectBase > >::iterator ObjectIterator;
for ( ObjectIterator it = object_list.begin(); it != object_list.end(); it++ )
(*it)->draw(view);
This would give you polymorphism and would be used just like it was a normal vector of pointers, but the shared_ptr would do the memory-management for you, destroying the object when the last shared_ptr referencing it is destroyed.
Note about C++11: In C++11 shared_ptr became part of the standard as std::shared_ptr, so Boost is no longer required for this approach. However, unless you really need shared ownership, it is recommended you use std::unique_ptr, which was newly introduced in C++11.
Using a ptr_vector
Using a ptr_vector you would do it like this:
boost::ptr_vector< ObjectBase > object_list;
And use it like this:
typedef boost::ptr_vector< ObjectBase >::iterator ObjectIterator;
for ( ObjectIterator it = object_list.begin(); it != object_list.end(); it++ )
(*it)->draw(view);
This would again be used like a normal vector of pointers, but this time the ptr_vector manages the lifetime of your objects. The difference to the first approach is, that here your objects get destroyed when the vector gets destroyed, whereas above they may live longer than the container, if other shared_ptrs referencing them exist.
Using a reference_wrapper
Using a reference_wrapper you would declare it like this:
std::vector< boost::reference_wrapper< ObjectBase > > object_list;
And then use it like this:
typedef std::vector< boost::reference_wrapper< ObjectBase > >::iterator
ObjectIterator;
for ( ObjectIterator it = object_list.begin(); it != object_list.end(); it++ )
it->draw(view);
Notice that you do not have to dereference the iterator first as in the above approaches. This does however only work if the lifetime of your objects is managed elsewhere and is guaranteed to be longer than that of the vector.
Note about C++11: reference_wrapper has also been standardized in C++11 and is now usable as std::reference_wrapper without Boost.
As pointed out in Maciej Hs answer, your first approach results in object slicing. In general you may want to look into iterators when using containers.
You wont get what You want with this code
class World{
vector<ObjectBaseClass> object_list;
public:
void generate(){
object_list.clear();
object_list.push_back(DerivedClass1());
object_list.push_back(DerivedClass2());
What is going to happen is called object slicing. You will get a vector of ObjectBaseClass.
To make polymorphism work You have to use some kind of pointers. There are probably some smart pointers or references in boost or other libraries that can be used and make the code much safer than the second proposed solution.
As for your first question, it is generally preferred to use automatically allocated objects rather than dynamically allocated objects (in other words, not to store pointers) so long as for the type in question, copy-construction and assignment is possible and not prohibitively expensive.
If the objects can't be copied or assigned, then you can't put them directly into a std::vector anyway, and so the question is moot. If the copying and/or assignment operations are expensive (e.g. the object stores a large amount of data), then you might want to store pointers for efficiency reasons. Otherwise, it is generally better not to store pointers for exactly the reason that you mentioned (automatic deallocation)
As for your second question, yes, that is another valid reason to store pointers. Dynamic dispatch (virtual method calls) work only on pointers and references (and you can't store references in a std::vector). If you need to store objects of multiple polymorphic types in the same vector, you must store pointers in order to avoid slicing.
Well, it depends on what you are trying to do with your vector.
If you don't use pointers, then it is a copy of the object you pass in that gets put on the vector. If it is a simple object, and/or you don't want to bother with keeping track of the storage for them, this may be exactly what you want. If it is something complex, or very time-consuming to construct and destruct, you might prefer to do that work only once each and pass pointers into the vector.

When to use pointers in C++

I just started learning about pointers in C++, and I'm not very sure on when to use pointers, and when to use actual objects.
For example, in one of my assignments we have to construct a gPolyline class, where each point is defined by a gVector. Right now my variables for the gPolyline class looks like this:
private:
vector<gVector3*> points;
If I had vector< gVector3 > points instead, what difference would it make? Also, is there a general rule of thumb for when to use pointers? Thanks in advance!
The general rule of thumb is to use pointers when you need to, and values or references when you can.
If you use vector<gVector3> inserting elements will make copies of these elements and the elements will not be connected any more to the item you inserted. When you store pointers, the vector just refers to the object you inserted.
So if you want several vectors to share the same elements, so that changes in the element are reflected in all the vectors, you need the vectors to contain pointers. If you don't need such functionality storing values is usually better, for example it saves you from worrying about when to delete all these pointed to objects.
Pointers are generally to be avoided in modern C++. The primary purpose for pointers nowadays revolves around the fact that pointers can be polymorphic, whereas explicit objects are not.
When you need polymorphism nowadays though it's better to use a smart pointer class -- such as std::shared_ptr (if your compiler supports C++0x extensions), std::tr1::shared_ptr (if your compiler doesn't support C++0x but does support TR1) or boost::shared_ptr.
Generally, it's a good idea to use pointers when you have to, but references or alternatively objects objects (think of values) when you can.
First you need to know if gVector3 fulfils requirements of standard containers, namely if the type gVector3 copyable and assignable. It is useful if gVector3 is default constructible as well (see UPDATE note below).
Assuming it does, then you have two choices, store objects of gVector3 directly in std::vector
std::vector<gVector3> points;
points.push_back(gVector(1, 2, 3)); // std::vector will make a copy of passed object
or manage creation (and also destruction) of gVector3 objects manually.
std::vector points;
points.push_back(new gVector3(1, 2, 3));
//...
When the points array is no longer needed, remember to talk through all elements and call delete operator on it.
Now, it's your choice if you can manipulate gVector3 as objects (you can assume to think of them as values or value objects) because (if, see condition above) thanks to availability of copy constructor and assignment operator the following operations are possible:
gVector3 v1(1, 2, 3);
gVector3 v2;
v2 = v1; // assignment
gVector3 v3(v2); // copy construction
or you may want or need to allocate objects of gVector3 in dynamic storage using new operator. Meaning, you may want or need to manage lifetime of those objects on your own.
By the way, you may be also wondering When should I use references, and when should I use pointers?
UPDATE: Here is explanation to the note on default constructibility. Thanks to Neil for pointing that it was initially unclear. As Neil correctly noticed, it is not required by C++ standard, however I pointed on this feature because it is an important and useful one. If type T is not default constructible, what is not required by the C++ standard, then user should be aware of potential problems which I try to illustrate below:
#include <vector>
struct T
{
int i;
T(int i) : i(i) {}
};
int main()
{
// Request vector of 10 elements
std::vector<T> v(10); // Compilation error about missing T::T() function/ctor
}
You can use pointers or objects - it's really the same at the end of the day.
If you have a pointer, you'll need to allocate space for the actual object (then point to it) any way. At the end of the day, if you have a million objects regardless of whether you are storing pointers or the objects themselves, you'll have the space for a million objects allocated in the memory.
When to use pointers instead? If you need to pass the objects themselves around, modify individual elements after they are in the data structure without having to retrieve them each and every time, or if you're using a custom memory manager to manage the allocation, deallocation, and cleanup of the objects.
Putting the objects themselves in the STL structure is easier and simpler. It requires less * and -> operators which you may find to be difficult to comprehend. Certain STL objects would need to have the objects themselves present instead of pointers in their default format (i.e. hashtables that need to hash the entry - and you want to hash the object, not the pointer to it) but you can always work around that by overriding functions, etc.
Bottom line: use pointers when it makes sense to. Use objects otherwise.
Normally you use objects.
Its easier to eat an apple than an apple on a stick (OK 2 meter stick because I like candy apples).
In this case just make it a vector<gVector3>
If you had a vector<g3Vector*> this implies that you are dynamically allocating new objects of g3Vector (using the new operator). If so then you need to call delete on these pointers at some point and std::Vector is not designed to do that.
But every rule is an exception.
If g3Vector is a huge object that costs a lot to copy (hard to tell read your documentation) then it may be more effecient to store as a pointer. But in this case I would use the boost::ptr_vector<g3Vector> as this automatically manages the life span of the object.