About automatic or manual deletion of vectors - c++

I read other questions trying to figure this out but I didn't find much like what I have in mind. I'm kinda new to C++ and I just don't want to have my C++ code to look like "C with classes", or in other words, if there is a good "C++ way of doing this", that's what I'm looking for, but I'm a bit confused. Well, to the problem.
I have a class, say MyClass. Now, in other class, say MyContainer, I have a vector<MyClass> vec.
Let's say I'm now creating a method that populates a MyClass object with any arbitrary stuff and then pushes it into vec. First question is: should I allocate and push the object like the following? (using vector<MyClass> vec)
MyClass *obj = new MyClass(args);
vec.push_back(*obj);
I am not sure this is right, but by my understanding, this could make me avoid having to manually delete every instance of MyClass I put into vec when the instance of MyContainer is of no use anymore.
What bugs me is that, like I said, this does not seem right anyway, and the other way I can figure out is declaring vector<MyClass*> and writing:
MyClass *obj = new MyClass(args);
vec.push_back(obj);
But this would make me write a method to delete every instance of MyClass I created before, right?
So... What should I use and, if both are actually right, when one is preferrable to the other?
However, if everything is wrong from the start, how can I do this?
Thank yall!
PS: by the way, MyContainer is created in main(). I'm planning to use heap allocation. Should I?
Edit: I can't use C++11.
PS2: This is part of an assignment, but I found it general enough to be of use for anyone, not just me.

You probably shouldn't use new unless you need the object to survive beyond the local scope of the variable.
Just declare it on the stack:
MyClass obj(args);
vec.push_back(obj);
In C++11, you can avoid any risk of extra copies of obj by using:
vec.emplace_back(args);

Whether or not you should allocate on the heap or the stack as suggested by #happydave is highly dependent on the nature of "MyClass", IMO. If you need any kind of polymorphic behavior (i.e. you might have specialized subclasses of MyClass), then you should have a container of pointers.
If you're concerned about needing to delete each of the entries individually, there are two things that might help you:
1 . Use shared_ptr. So your code might look like this:
typedef std::shared_ptr<MyClass> MyClassPtr;
...
vector<MyClassPtr> vec;
vec.push_back(MyClassPtr(new MyClass());
The smart pointer will automatically delete MyClass when there are no more references to it.
2 . If you use bare pointers, you can still delete all the pointers with one line of code using std::for_each. This is described here: Can I call `delete` on a vector of pointers in C++ via for_each <algorithm>?
If you don't need polymorphic behavior and your class is copyable (either you gave it a copy constructor or the default copy is good for your implementation), then you can allocate on the stack.

Related

How to store class member objects in C++

I am trying to write a simple game using C++ and SDL. My question is, what is the best practice to store class member variables.
MyObject obj;
MyObject* obj;
I read a lot about eliminating pointers as much as possible in similar questions, but I remember that few years back in some books I read they used it a lot (for all non trivial objects) . Another thing is that SDL returns pointers in many of its functions and therefor I would have to use "*" a lot when working with SDL objects.
Also am I right when I think the only way to initialize the first one using other than default constructor is through initializer list?
Generally, using value members is preferred over pointer members. However, there are some exceptions, e.g. (this list is probably incomplete and only contains reason I could come up with immediately):
When the members are huge (use sizeof(MyObject) to find out), the difference often doesn't matter for the access and stack size may be a concern.
When the objects come from another source, e.g., when there are factory function creating pointers, there is often no alternative to store the objects.
If the dynamic type of the object isn't known, using a pointer is generally the only alternative. However, this shouldn't be as common as it often is.
When there are more complicated relations than direct owner, e.g., if an object is shared between different objects, using a pointer is the most reasonable approach.
In all of these case you wouldn't use a pointer directly but rather a suitable smart pointer. For example, for 1. you might want to use a std::unique_ptr<MyObject> and for 4. a std::shared_ptr<MyObject> is the best alternative. For 2. you might need to use one of these smart pointer templates combined with a suitable deleter function to deal with the appropriate clean-up (e.g. for a FILE* obtained from fopen() you'd use fclose() as a deleter function; of course, this is a made up example as in C++ you would use I/O streams anyway).
In general, I normally initialize my objects entirely in the member initializer list, independent on how the members are represented exactly. However, yes, if you member objects require constructor arguments, these need to be passed from a member initializer list.
First I would like to say that I completely agree with Dietmar Kühl and Mats Petersson answer. However, you have also to take on account that SDL is a pure C library where the majority of the API functions expect C pointers of structs that can own big chunks of data. So you should not allocate them on stack (you shoud use new operator to allocate them on the heap). Furthermore, because C language does not contain smart pointers, you need to use std::unique_ptr::get() to recover the C pointer that std::unique_ptr owns before sending it to SDL API functions. This can be quite dangerous because you have to make sure that the std::unique_ptr does not get out of scope while SDL is using the C pointer (similar problem with std::share_ptr). Otherwise you will get seg fault because std::unique_ptr will delete the C pointer while SDL is using it.
Whenever you need to call pure C libraries inside a C++ program, I recommend the use of RAII. The main idea is that you create a small wrapper class that owns the C pointer and also calls the SDL API functions for you. Then you use the class destructor to delete all your C pointers.
Example:
class SDLAudioWrap {
public:
SDLAudioWrap() { // constructor
// allocate SDL_AudioSpec
}
~SDLAudioWrap() { // destructor
// free SDL_AudioSpec
}
// here you wrap all SDL API functions that involve
// SDL_AudioSpec and that you will use in your program
// It is quite simple
void SDL_do_some_stuff() {
SDL_do_some_stuff(ptr); // original C function
// SDL_do_some_stuff(SDL_AudioSpec* ptr)
}
private:
SDL_AudioSpec* ptr;
}
Now your program is exception safe and you don't have the possible issue of having smart pointers deleting your C pointer while SDL is using it.
UPDATE 1: I forget to mention that because SDL is a C library, you will need a custom deleter class in order to proper manage their C structs using smart pointers.
Concrete example: GSL GNU scientific library. Integration routine requires the allocation of a struct called "gsl_integration_workspace". In this case, you can use the following code to ensure that your code is exception safe
auto deleter= [](gsl_integration_workspace* ptr) {
gsl_integration_workspace_free(ptr);
};
std::unique_ptr<gsl_integration_workspace, decltype(deleter)> ptr4 (
gsl_integration_workspace_alloc (2000), deleter);
Another reason why I prefer wrapper classes
In case of initialization, it depends on what the options are, but yes, a common way is to use an initializer list.
The "don't use pointers unless you have to" is good advice in general. Of course, there are times when you have to - for example when an object is being returned by an API!
Also, using new will waste quite a bit of memory and CPU-time if MyObject is small. Each object created with new has an overhead of around 16-48 bytes in a typical modern OS, so if your object is only a couple of simple types, then you may well have more overhead than actual storage. In a largeer application, this can easily add up to a huge amount. And of course, a call to new or delete will most likely take some hundreds or thousands of cycles (above and beyond the time used in the constructor). So, you end up with code that runs slower and takes more memory - and of course, there's always some risk that you mess up and have memory leaks, causing your program to potentially crash due to out of memory, when it's not REALLY out of memory.
And as that famous "Murphy's law states", these things just have to happen at the worst possible and most annoying times - when you have just done some really good work, or when you've just succeeded at a level in a game, or something. So avoiding those risks whenever possible is definitely a good idea.
Well, creating the object is a lot better than using pointers because it's less error prone. Your code doesn't describe it well.
MyObj* foo;
foo = new MyObj;
foo->CanDoStuff(stuff);
//Later when foo is not needed
delete foo;
The other way is
MyObj foo;
foo.CanDoStuff(stuff);
less memory management but really it's up to you.
As the previous answers claimed the "don't use pointers unless you have to" is a good advise for general programming but then there are many issues that could finally make you select the pointers choice. Furthermore, in you initial question you are not considering the option of using references. So you can face three types of variable members in a class:
MyObject obj;
MyObject* obj;
MyObject& obj;
I use to always consider the reference option rather than the pointer one because you don't need to take care about if the pointer is NULL or not.
Also, as Dietmar Kühl pointed, a good reason for selecting pointers is:
If the dynamic type of the object isn't known, using a pointer is
generally the only alternative. However, this shouldn't be as common
as it often is.
I think this point is of particular importance when you are working on a big project. If you have many own classes, arranged in many source files and you use them in many parts of your code you will come up with long compilation times. If you use normal class instances (instead of pointers or references) a simple change in one of the header file of your classes will infer in the recompilation of all the classes that include this modified class. One possible solution for this issue is to use the concept of Forward declaration, which make use of pointers or references (you can find more info here).

understanding the smart pointer boost in c++

I am new to c++ as well as smart pointer.
I have a code like this.
Example* Example::get_instance() {
Example* example = new Example();
return example;
}
I am trying to convert it to smart pointer like this
shared_ptr<Example> Example::get_instance() {
shared_ptr<Example> example (new Example());
return example;
}
Is this the correct way because when i am trying to call this from another class its not working.I am trying to implement a singleton object.
You are creating a new Example object every time the object is requested, That is a memory leak, an you are also returning a different object every time. Try this instead:
Example & Example::get_instance() {
static Example example;
return example;
}
Also please note the following advices for your code:
when creating smart pointers prefer make_shared instead of shared_ptr<YourType>(new YourType(...)). The reason why can be found here. Relevant excerpt:
This function typically allocates memory for the T object and for the
shared_ptr's control block with a single memory allocation (it is a
non-binding requirement in the Standard). In contrast, the declaration
std::shared_ptr p(new T(Args...)) performs at least two memory
allocations, which may incur unnecessary overhead. Moreover,
f(shared_ptr(new int(42)), g()) can lead to memory leak if g
throws an exception. This problem doesn't exist if make_shared is
used.
understand the difference between std::unique_ptr and std::shared_ptr. For your case, a std::unique_ptr would have been better, but there is an even simpler solution to your problem, which I have shown above.
in general, avoid pointers when you can use references instead, they're easier to use and code looks a bit cleaner.
and finally, do you REALLY want a singleton? I just have to be ask. I've been working full-time as a programmer for almost 4 years now. Not that long, I know, but enough to have encountered the situation where I regretted that I or someone else used the Singleton pattern instead of passing the reference to my object down the call chain.
Try to avoid singletons, you may later find your code using the singleton might in the end want to work on multiple instances of your Example object instead of calling Example::get_instance and only work on that single instances. So when you'll have that revelation, (and it might be only a matter of time), you'll have major refactoring ahead of you.
So, "Beware, there be dragons!".

Element of shared_array as shared_ptr?

If I have a boost::shared_array<T> (or a boost::shared_ptr<T[]>), is there a way to obtain a boost::shared_ptr<T> which shares with the array?
So for example, I might want to write:
shared_array<int> array(new int[10]);
shared_ptr<int> element = &array[2];
I know that I can't use &array[2], because it just has type int *, and it would be dangerous for shared_ptr<int> to have an implicit constructor that will take that type. Ideally shared_array<int> would have an instance method on it, something like:
shared_ptr<int> element = array.shared_ptr_to(2);
Unfortunately I can't find anything like this. There is an aliasing constructor on shared_ptr<int> which will alias with another shared_ptr<T>, but it won't allow aliasing with shared_array<T>; so I can't write this either (it won't compile):
shared_ptr<int> element(array, &array[2]);
//Can't convert 'array' from shared_array<int> to shared_ptr<int>
Another option I played with was to use std::shared_ptr<T> (std instead of boost). The specialisation for T[] isn't standardised, so I thought about defining that myself. Unfortunately, I don't think that's actually possible in a way that doesn't break the internals of the aliasing constructor, as it tries to cast my std::shared_ptr<T[]> to its own implementation-specific supertype, which is no longer possible. (Mine is currently just inheriting from the boost one at the moment.) The nice thing about this idea would have been that I could implement my instance shared_ptr_to method.
Here's another idea I experimented with, but I don't think it's efficient enough to be acceptable as something we're potentially going to use throughout a large project.
template<typename T>
boost::shared_ptr<T> GetElementPtr(const boost::shared_array<T> &array, size_t index) {
//This deleter works by holding on to the underlying array until the deleter itself is deleted.
struct {
boost::shared_array<T> array;
void operator()(T *) {} //No action required here.
} deleter = { array };
return shared_ptr<T>(&array[index], deleter);
}
The next thing I'm going to try is upgrading to Boost 1.53.0 (we currently only have 1.50.0), using shared_ptr<T[]> instead of shared_array<T>, and also always using boost instead of std (even for non-arrays). I'm hoping this will then work, but I haven't had a chance to try it yet:
shared_ptr<int[]> array(new int[10]);
shared_ptr<int> element(array, &array[2]);
Of course I'd still prefer the instance method syntax, but I guess I'm out of luck with that one (short of modifying Boost):
shared_ptr<int> element = array.shared_ptr_to(2);
Anyone else have any ideas?
You are doing strange stuff.
Why do you need shared_ptr to element? Do you want element of array be passed somewhere else and hold down your array from removal?
If yes, than std::vector<shared_ptr<T>> is more suited for that. That solution is safe, standard and has fine granularity on objects removal
boost::shared_ptr does not seem to support this nativly. Maybe you can work around this with a custom deleter. But std::shared_ptr offers a special constructor to support what you want:
struct foo
{
int a;
double b;
};
int main()
{
auto sp1 = std::make_shared<foo>();
std::shared_ptr<int> sp2 (sp1,&sp1->a);
}
Here, sp1 and sp2 share ownership of the foo object but sp2 points to a member of it. If sp1 is destroyed, the foo object will still be alive and sp2 will still be valid.
Here's what I did in the end.
I made my own implementation of shared_array<T>. It effectively extends shared_ptr<vector<T>>, except it actually extends my own wrapper for vector<T> so that the user can't get the vector out. This means I can guarantee it won't be resized. Then I implemented the instance methods I needed - including weak_ptr_to(size_t) and of course operator[].
My implementation uses std::make_shared to make the vector. So the vector allocates its internal array storage separately from the control block, but the vector itself becomes a member of the control block. It's therefore about equivalent to forgetting to use std::make_shared for a normal type - but because these are arrays, they're likely to be largeish and few, so it's less important.
I could also create an implementation that's based on shared_ptr<T> but with default_delete<T[]> or whatever is required, but it would have to allocate the array separately from the control block (so there's not much saving versus vector). I don't think there's a portable way to embed a dynamically sized array in the control block.
Or my implementation could be based on boost::shared_array<T>, and use the custom deleter when taking element pointers (as per the example in the question). That's probably worse in most cases, because instead of a one-time hit allocating the array, we get a hit every time we take an aliased pointer (which could happen a lot with very short-lived ones).
I think the only reasonable way to get it even more optimal would be to use the latest boost (if it works; I didn't get as far as trying it before I changed my mind, mainly because of the desire for my own instance members). And of course this means using the boost ones everywhere, even for single objects.
But, the main advantage with what I went with is Visual Studio's debugger is (I'm told) good at displaying the contents of std::shared_ptrs and std::vectors, and (we expect) less good at analysing the contents of boost things or custom things.
So I think what I've done is basically optimal. :)

Why is this allocation of a vector not accepted?

So I have declared a vector in my class header like this:
...
private:
vector<Instruction> instructions;
...
Then in the .cpp implementation in the constructor, I try to initialize it like this:
instructions = new vector<Instruction>();
Xcode tells me: No viable overloaded '='
I am basically trying to get this class to behave like I would expect in java, where instances of the class retain this vector. Thats why I wanted to dynamically allocate it using new, so as to make sure that it doesn't get lost on the stack or something. Any help would be appreciated with this, thanks so much.
In order to do what you're trying to do the instructions = new vector<Instruction>() line is entirely unnecessary. Simply remove it. The vector will automatically get default-constructed when an instance of your class gets constructed.
An alternative is to make instructions into a pointer, but there doesn't appear to be any reason to do this here.
when you write
vector<Instruction> instructions;
you already have instantiated instructions to whatever memory model the user of your class is using e.g.
class YourClass
{
vector<Instruction> instructions;
};
...
int main()
{
YourClass class1; // stack
std::unique_ptr<YourClass> class2(new YourClass); // heap
...
}
In your class, you declare a std::vector<Instruction>. new vector<Instruction>(); returns you a std::vector<Instruction>*.
operator new returns a pointer, so you have a type mismatch.
The real issue is the fact that you are doing it at all. Do you have a good reason for dynamically allocating that vector? I doubt it, just omit that entirely as it will be allocated along with instances of your type.
You have a member value but you try to initialize it from a vector<Instruction>*. Initialize it from vector<Instruction> or change the declaration to a pointer. If you go down the second route, you need to observe the rule of three.
You might also want to get a decent C++ book from this list.
Also, I think you have a using namespace std; in your header which is bad.
Do not use new in C++ unless you know what you are doing. (Which you do not, currently.)
Instead use automatic objects. You already defined instructions to be an automatic object. You just need to init it as if it were one:
class wrgxl {
public:
wrgxl()
: instructions() // this initializes the vector using its default constructor
{
// nothing needed here
}
...
private:
vector<Instruction> instructions;
...
};
The initialization of instructions in the constructor's initialization list is optional, though, if you only want to call the default constructor anyway. So in this case, this would be enough:
wrgxl()
{
}
If you wanted to dynamically allocate a vector, you would need to make instructions a pointer to a vector. But this rarely ever make sense, since the vector already allocates its data dynamically, but wraps this, so you do not have to deal with the ugly details resulting from this.
One of those details is that, if you have a dynamically allocated object in a class, you will then have to worry about destruction, copy construction, and copy assignment for that class.
As Kerrek already pointed out, you will need to have a good C++ book in order to properly learn C++. Make your pick.
I think you are confusing C++'s with C#'s syntax.
First, unlike in many languages, variables allocated on the stack (such as yours), are initialized by calling the default constructor, so I suspect that what you are doing is unnecessary.
Second, in order to do what you are trying to do, you use the following syntax:
instructions = vector<Instruction>();
however, as I said, this is likely redundant (and wasteful on a non-optimizing compiler as it might call both the constructor and the assignment operator). A much better way to do this is found in sbi's answer.
Third, unlike in C#, the new operator allocates memory on the heap and returns a pointer to the newly allocated data. Your variable instructions is not a pointer, thus the error.

C++ containers on classes, returning pointers

I'm having some trouble to find the best way to accomplish what I have in mind due to my inexperience. I have a class where I need to a vector of objects. So my first question will be:
is there any problem having this: vector< AnyType > container* and then on the constructor initialize it with new (and deleting it on the destructor)?
Another question is: if this vector is going to store objects, shouldn't it be more like vector< AnyTipe* > so they could be dynamically created? In that case how would I return an object from a method and how to avoid memory leaks (trying to use only STL)?
Yes, you can do vector<AnyType> *container and new/delete it. Just be careful when you do subscript notation to access its elements; be sure to say (*container)[i], not container[i], or worse, *container[i], which will probably compile and lead to a crash.
When you do a vector<AnyType>, constructors/destructors are called automatically as needed. However, this approach may lead to unwanted object copying if you plan to pass objects around. Although vector<AnyType> lends itself to better syntactic sugar for the most obvious operations, I recommend vector<AnyType*> for non-primitive objects simply because it's more flexible.
is there any problem having this: vector< AnyType > *container and then on the constructor initialize it with new (and deleting it on the destructor)
No there isn't a problem. But based on that, neither is there a need to dynamically allocate the vector.
Simply make the vector a member of the class:
class foo
{
std::vector<AnyType> container;
...
}
The container will be automatically constructed/destructed along with the instance of foo. Since that was your entire description of what you wanted to do, just let the compiler do the work for you.
Don't use new and delete for anything.
Sometimes you have to, but usually you don't, so try to avoid it and see how you get on. It's hard to explain exactly how without a more concrete example, but in particular if you're doing:
SomeType *myobject = new SomeType();
... use myobject for something ...
delete myobject;
return;
Then firstly this code is leak-prone, and secondly it should be replaced with:
SomeType myobject;
... use myobject for something (replacing -> with . etc.) ...
return;
Especially don't create a vector with new - it's almost always wrong because in practice a vector almost always has one well-defined owner. That owner should have a vector variable, not a pointer-to-vector that they have to remember to delete. You wouldn't dynamically allocate an int just to be a loop counter, and you don't dynamically allocate a vector just to hold some values. In C++, all types can behave in many respects like built-in types. The issues are what lifetime you want them to have, and (sometimes) whether it's expensive to pass them by value or otherwise copy them.
shouldn't it be more like vector< AnyTipe* > so they could be dynamically created?
Only if they need to be dynamically created for some other reason, aside from just that you want to organise them in a vector. Until you hit that reason, don't look for one.
In that case how would I return an object from a method and how to avoid memory leaks (trying to use only STL)?
The standard libraries don't really provide the tools to avoid memory leaks in all common cases. If you must manage memory, I promise you that it is less effort to get hold of an implementation of shared_ptr than it is to do it right without one.