Delete Inherited class Pointer Array in C++ - c++

I have a class A like:
class A
{
int a;
}
And, Also I have class B that inherited class A:
class B : public A
{
int b;
public:
static A** ReturnAPtrArray(int size);
}
Then, I make Array having A class Pointer in class B.
A** B::ReturnAPtrArray(int size)
{
A** array = new A*[size];
for(int i = 0; i< size; i++)
{
array[i] = new A();
}
return array;
}
In main func, I Called class B's ReturnAPtrArray() func.
void main(void)
{
int size = 100;
A** aptrArray = B::ReturnAPtrArray(size);
--------Do Something
delete[] aptrArray;
}
This main func makes memory leak. So I deleted every pointers like this:
void main(void)
{
int size = 100;
A** aptrArray = B::ReturnAPtrArray(size);
--------Do Something
for(int i = 0; i< size; i++)
{
delete aptrArray[i];
}
delete[] aptrArray;
}
After modified main func, memory leaks were disappeared.
If I want to free memory, should I delete all pointers in Pointer Array?
Is there any other options?

If I want to free memory, should I delete all pointers in Pointer Array?
Yes you should
delete[] deletes only the array it self.
Since you have a array of pointers you must delete every pointer element individually.
As for other options you can use smart pointers.
Example:
#include <memory>
#include <vector>
int main()
{
std::vector<std::shared_ptr<A>> array;
for(int i = 0; i < 100; i++)
{
array.push_back(std::make_shared<B>());
}
}
when the array goes out of scope it deletes it self

It is important to distinguish between polymorphic-ownership and polymorphic use. Polymorphic ownership is when you want to own a thing (or many things) that are are of an unknown type. Polymorphic use is when you want to manipulate a thing when you don't know what it is. Your example doesn't really make clear why you use inheritance at all, so I will explain both.
If you only create B's just declare them as B's. If you want to pass a set of B's to a function that doesn't know they are B's, the simply create a vector of B's and pass them as pointer-to-A.
Like this ...
std::vector<B> myBs(5); // create 5 default B's
for (const auto& thisB: myBs) Fn(&thisB); // cast a ptr-to-B to a ptr-to-A
Keeping it simple like this will make your life a lot simpler, as this code is type-safe.
If on the other hand you want to own a list of things that might be a B, or might not, but definitely inherits from A. Use something like this.
std::vector<std::unique_ptr<A>> my_maybe_bs_might_not;
This pattern might seem superficially simpler, but it comes with a lot of gotcha's. For example, you must use must use a virtual destuctor. This in turn invokes the rule-of-3/5. Simply put, if the compiler doesn't know a thing is, you have to tell it how it can be moved/copied. If you don't, the compiler will probably do the wrong thing.
A simpler (assuming you have C++17) scheme for polymorphic-ownership is using a variant. When you use a variant, you must list all things it might be, this can include smart pointers.
using MaybeB = std::variant<std::unique_ptr<B>, std::unique_ptr<C>>;
std::vector<MaybeB> my_maybe_bs_might_not;
This pattern allows the compiler to generate all the right code for you, while making it simple to add new classes. The only downside is that because you must list all the things you might want to own. This makes it a bad choice for a library-level system, where the user of the library might want to write their own class (derived from A) and add it to your list.
The general advice is to pick the simplest scheme possible, which in general means avoiding polymorphic ownership unless that is really required.

Related

Virtual functions and vectors(C++) [duplicate]

I have a tricky situation. Its simplified form is something like this
class Instruction
{
public:
virtual void execute() { }
};
class Add: public Instruction
{
private:
int a;
int b;
int c;
public:
Add(int x, int y, int z) {a=x;b=y;c=z;}
void execute() { a = b + c; }
};
And then in one class I do something like...
void some_method()
{
vector<Instruction> v;
Instruction* i = new Add(1,2,3)
v.push_back(*i);
}
And in yet another class...
void some_other_method()
{
Instruction ins = v.back();
ins.execute();
}
And they share this Instruction vector somehow. My concern is the part where I do "execute" function. Will it work? Will it retain its Add type?
No, it won't.
vector<Instruction> ins;
stores values, not references. This means that no matter how you but that Instruction object in there, it'll be copied at some point in the future.
Furthermore, since you're allocating with new, the above code leaks that object. If you want to do this properly, you'll have to do
vector<Instruction*> ins
Or, better yet:
vector< std::reference_wrapper<Instruction> > ins
I like this this blog post to explain reference_wrapper
This behavior is called object slicing.
So you will need some kind of pointer. A std::shared_ptr works well:
typedef shared_ptr<Instruction> PInstruction;
vector<PInstruction> v;
v.emplace_back(make_shared<Add>());
PInstruction i = v[0];
Keep in mind that PInstruction is reference-counted, so that the copy constructor of PInstruction will create a new "reference" to the same object.
If you want to make a copy of the referenced object you will have to implement a clone method:
struct Instruction
{
virtual PInstruction clone() = 0;
...
}
struct Add
{
PInstruction clone() { return make_shared<Add>(*this); }
...
}
PInstruction x = ...;
PInstruction y = x->clone();
If performance is an issue than you can look at std::unique_ptr, this is a little trickier to manage as move semantics are always required, but it avoids the cost of some atomic operations.
You can also use raw pointers and manage the memory manually with some sort of memory pool architecture.
The underlying problem is that to have a polymorphic type the compiler doesn't know how big the subclasses are going to be, so you can't just have a vector of the base type, as it won't have the extra space needed by subclasses. For this reason you will need to use pass-by-reference semantics as described above. This stores a pointer to the object in the vector and then stores the object on the heap in blocks of different sizes depending on what the subclass needs.
No, that will not work; you are "slicing" the Add object, and only inserting its Instruction part into the array. I would recommend that you make the base class abstract (e.g. by making execute pure virtual), so that slicing gives a compile error rather than unexpected behaviour.
To get polymorphic behaviour, the vector needs to contain pointers to the base class.
You will then need to be careful how you manage the objects themselves, since they are no longer contained in the vector. Smart pointers may be useful for this; and since you're likely to be dynamically allocating these objects, you should also give the base class a virtual destructor to make sure you can delete them correctly.
You may want to do a couple things, A: change the type of "v" to "vector", B: managed your memory with the "delete" operator. To answer your question, with this approach, yes, but you will only be able to access the interface from "Instruction", if you KNOW the type of something an "Instruction" pointer is pointing to I would suggest using dynamic_cast if you need to access the interface from, say, "Add".

Storing an inherited class in a vector [duplicate]

I have a tricky situation. Its simplified form is something like this
class Instruction
{
public:
virtual void execute() { }
};
class Add: public Instruction
{
private:
int a;
int b;
int c;
public:
Add(int x, int y, int z) {a=x;b=y;c=z;}
void execute() { a = b + c; }
};
And then in one class I do something like...
void some_method()
{
vector<Instruction> v;
Instruction* i = new Add(1,2,3)
v.push_back(*i);
}
And in yet another class...
void some_other_method()
{
Instruction ins = v.back();
ins.execute();
}
And they share this Instruction vector somehow. My concern is the part where I do "execute" function. Will it work? Will it retain its Add type?
No, it won't.
vector<Instruction> ins;
stores values, not references. This means that no matter how you but that Instruction object in there, it'll be copied at some point in the future.
Furthermore, since you're allocating with new, the above code leaks that object. If you want to do this properly, you'll have to do
vector<Instruction*> ins
Or, better yet:
vector< std::reference_wrapper<Instruction> > ins
I like this this blog post to explain reference_wrapper
This behavior is called object slicing.
So you will need some kind of pointer. A std::shared_ptr works well:
typedef shared_ptr<Instruction> PInstruction;
vector<PInstruction> v;
v.emplace_back(make_shared<Add>());
PInstruction i = v[0];
Keep in mind that PInstruction is reference-counted, so that the copy constructor of PInstruction will create a new "reference" to the same object.
If you want to make a copy of the referenced object you will have to implement a clone method:
struct Instruction
{
virtual PInstruction clone() = 0;
...
}
struct Add
{
PInstruction clone() { return make_shared<Add>(*this); }
...
}
PInstruction x = ...;
PInstruction y = x->clone();
If performance is an issue than you can look at std::unique_ptr, this is a little trickier to manage as move semantics are always required, but it avoids the cost of some atomic operations.
You can also use raw pointers and manage the memory manually with some sort of memory pool architecture.
The underlying problem is that to have a polymorphic type the compiler doesn't know how big the subclasses are going to be, so you can't just have a vector of the base type, as it won't have the extra space needed by subclasses. For this reason you will need to use pass-by-reference semantics as described above. This stores a pointer to the object in the vector and then stores the object on the heap in blocks of different sizes depending on what the subclass needs.
No, that will not work; you are "slicing" the Add object, and only inserting its Instruction part into the array. I would recommend that you make the base class abstract (e.g. by making execute pure virtual), so that slicing gives a compile error rather than unexpected behaviour.
To get polymorphic behaviour, the vector needs to contain pointers to the base class.
You will then need to be careful how you manage the objects themselves, since they are no longer contained in the vector. Smart pointers may be useful for this; and since you're likely to be dynamically allocating these objects, you should also give the base class a virtual destructor to make sure you can delete them correctly.
You may want to do a couple things, A: change the type of "v" to "vector", B: managed your memory with the "delete" operator. To answer your question, with this approach, yes, but you will only be able to access the interface from "Instruction", if you KNOW the type of something an "Instruction" pointer is pointing to I would suggest using dynamic_cast if you need to access the interface from, say, "Add".

C++ polymorphic class pointer in vector

Let's say I have the following code which, in short, has:
a BaseClass with a pointer to a PointerClass
a ChildClass that inherits from BaseClass
a HolderClass that has an std::vector of ChildClasss and an std::vector of BaseClass*s:
The entire code is as follows:
#include <stdlib.h>
#include <time.h>
#include <vector>
class PointerClass {
public:
int num;
double num2;
PointerClass() {
srand(time(NULL));
num = rand() % 100;
num2 = rand() % 100 / 2.0;
}
};
class BaseClass {
public:
PointerClass *pointerClass;
};
class ChildClass: public BaseClass {
public:
ChildClass() {
pointerClass = new PointerClass();
}
};
class HolderClass {
public:
std::vector<BaseClass*> basePointerVec;
std::vector<ChildClass> childVec;
HolderClass() {
}
void addParentClass() {
ChildClass childClass = ChildClass();
childVec.push_back(childClass);
basePointerVec.push_back(&childClass);
}
};
int main(int argc, const char * argv[]) {
HolderClass holderClass = HolderClass();
for (int count = 0; count < 20; count++) {
holderClass.addParentClass();
}
for (int count = 0; count < holderClass.basePointerVec.size(); count++) {
delete holderClass.basePointerVec[count]->pointerClass;
}
return 0;
}
My problem is, after adding a pointer to the ChildClass into the std::vector<BaseClass*> basePointerVec and the actual ChildClass into the std::vector<ChildClass> childVec in the addParentClass() method in HolderClass, the data in basePointerVec andchildVec are completely different.
Furthermore, when I try to free the PointerClasses from the childVec, everything works fine. But when I try to free them from the basePointerVec instead, I get an error telling my I'm trying to free a pointer I have not allocated memory for.
And sure enough, when I use breakpoints to inspect everything, I find some funky behavior. It seems that every time I call ChildClass childClass = ChildClass(); in addParentClass(), every pointer in basePointerVec gets changed to point to the newly created ChildClass's BaseClass.
The point of me doing this in my actual program is to take advantage of polymorphism and have multiple classes inherit from BaseClass.
So my question is, why is every pointer in the vector being changed to point to the newly created class and how can I fix it?
P.S. sorry for the length of this question, it's as short as I could possibly make it
childVec.push_back(childClass);
The push_back method of the class vector copies the object. So the added object is not the same as childClass in this case.
You can't delete the pointers from basePointerVec because they were not allocated with new but they were allocated locally and they are deleted at the end of addParentClass. So, the code of addParent is wrong because the pointer you push in the vector is no longer valid after the end of the method and may cause segmentation faults(in best case). Here is a suggestion of improvement:
void addParentClass() {
ChildClass* childClass = new ChildClass();
childVec.push_back(*childClass);
basePointerVec.push_back(childClass);
}
The memory is now allocated dynamically, you should make sure to free these pointers with delete.
EDIT:
void addParentClass() {
childVec.push_back(ChildClass());
basePointerVec.push_back(&childVec.back());
}
And if you are using C++11:
void addParentClass() {
childVec.emplace_back();
basePointerVec.push_back(&childVec.back());
}
The other answers already addressed the specific problem in your code. Here are two general points about your program above that will help you IMHO avoid all sorts of problems in the future:
When you define a class, esp. one which can be subclassed, always make the dtor public virtual except if you have a specific reason not too.
Always store resources in classes with the RAII principle:
Except for a good reason, you should never have a naked member pointer. Use a shared_ptr member instead.
Except for a good reason, you should never have a vector of naked pointers. Again use a vector of shared pointers.
Using this, hopefully, you won't need to track in your head what got destroyed when before something was copied to whatever, etc. It will make it harder to mix up heap objects and stack objects.
Look here:
void addParentClass() {
ChildClass childClass = ChildClass();
childVec.push_back(childClass);
basePointerVec.push_back(&childClass);
}
Your objects are not allocated on the heap. They are values and in basePointerVec you put their addresses (which don't make sense anyway after addParentClass() returns). Don't try to delete those, that will crash your program. They will be automatically deleted when childVec goes out of scope.
When addParentClass returns, the childClass object is destroyed. Therefore, the pointer to that object, that you put into basePointerVec cannot be used anymore.
You are creating a local variable that is destroyed as soon addParentClass goes out of scope. Also see the answers to this question which explains what happens when you don't use new. So the vector of BaseClass pointers are pointing to an object that is destroyed, and the childVec vector of objects are creating new copies when you use push_back, from this page:
The new element is initialized as a copy of value.
This is why the two vectors are pointing to different objects. You could create a destructor for the classes and add debugging prints to the destructor and the constructor to see when the objects are created/destroyed, this should give you a better idea of what is happening in what order.

c++ struct, how to create struct objects dynamically,

I have a struct like this:
struct MYSTRUCT {
....
};
if I create struct objects with a for loop like this:
for(int i = 0; i < 2; i++){
MYSTRUCT *mystruct;
}
will mystruct be the same every time because of the same name? What's the difference between the code above and this code:
MYSTRUCT *mystruct0;
MYSTRUCT *mystruct1;
How can I create different struct objects in a simpler way?
MYSTRUCT *mystruct0;
MYSTRUCT *mystruct1;
...
MYSTRUCT *mystruct99;
MYSTRUCT *mystruct100;
If I do the way below, will all the struct pointers same or they are isolated from each other?
vector<MYSTRUCT *> mystructs;
for(int i = 0; i < 100; i++){
MYSTRUCT *mystruct;
mystructs.push_back();
}
First off, you should never try to generate variable names.
it's just not the way to do it.
You should use a container (like in your example a std::vector) which is exactly what you want : something to put several other things of the same type.
In your example :
struct MyStruct { // Don't name your struct in all caps.
// it's generally reserved for MACROS. Use CamelCase
// blablabla
}
Do not use pointers unless you need to, usually it is much easier and much more efficient to use values. If you need to pass one of the elements of your vector to a function, so this function can modify it, you can pass an iterator to that element.
vector<MyStruct> mystructs;
for(int i = 0; i < 100; i++){
mystructs.emplace_back(MyStruct{});
}
Also if your struct has fields that need to be initialized, you might want to use an initializer list or define a constructor.
If you need to use dynamic allocation you can do something like this :
vector<MyStruct*> mystructs;
for(int i = 0; i < 100; i++){
mystructs.emplace_back(new MyStruct{});
}
Now the vector contains the pointers, not the objects. Each object is allocated individually in his own memory emplacement, therefore there is no garantee that they are next to each other.
This matters tremendously for performance : Pointers give you indirection.
Indirection leads to pain. Pain leads to anger ... blablabla => Welcome to the dark side.
A struct is a datatype that you defined, when you do MYSTRUCT *mystruct you declare a pointer to a MYSTRUCT object and the pointer is called mystruct It is the same thing you do with int *pointer_to_int.
For you first version, you redeclare mystruct at each iteration while your second declares two independant variables. If you want to declare a set of MYSTRUCT* easily, use an array of MYSTRUCT*: MYSTRUCT* mystruct_pointers_array[100].
NOTE MYSTRUCT* pointers are different than MYSTRUCT variables, you need to dereference the pointer to access to MYSTRUCT elements. E.g. mystruct->x.
In your example code:
for(int i = 0; i < 2; i++){
MYSTRUCT *mystruct;
}
You're not creating objects at all. All you're doing is declaring pointers to MYSTRUCT. These pointers are uninitialized and therefore don't point to anything (yet). Moreover, the pointer (mystruct) itself is allocated on the stack and has a lifetime limited to the scope of your for-loop.
I am not sure what you are trying to achieve, but if you need multiple objects of type MYSTRUCT, you should not try to create them in a loop like that. Rather, declare an array or std::vector and initialize appropriately. I will leave it to you to figure out how to do this. When you do, be aware of the difference between static and dynamic arrays, and their consequences for memory management!
EDIT:
On request, I'll elaborate on the final snippet you provided:
vector<MYSTRUCT *> mystructs;
for(int i = 0; i < 100; i++){
MYSTRUCT *mystruct;
mystructs.push_back();
}
What happens here is you declare an empty vector of pointers to MYSTRUCT. So far so good. Now, judging on the body, you want to populate this vector with pointers to actual objects, but this is not happening in your code. I doubt this will even compile, given that push_back requires a MYSTRUCT* as an argument. Therefore, to do what you intend to do, your code should in each iteration:
Allocate an object on the heap.
Push a pointer to this object to the back of the vector.
This would look like the following:
vector<MYSTRUCT*> vec;
for (int i = 0; i != n; ++i) // pre-incr is good practice!
vec.push_back(new MYSTRUCT); // optionally add constructor arguments
However, this introduces you to new responsibilities: you are the one requesting the memory explicitly using new, so you should free the memory explicitly using delete. Unless MYSTRUCT is polymorphic (contains virtual members), you can easily circumvent this (even it it is polymorphic, you shouldn't do this, but that's another topic).
The answer to this problem is: don't store pointers, store objects:
vector<MYSTRUCT> vec; // no pointer!
for (int i = 0; i < 100; ++i)
vec.push_back(MYSTRUCT()); // create an unnamed instance and copy to the back of the vec
There, you have just created a vector of n MYSTRUCT instances. No pointers, no new and delete, simple and easy!
Use a std::vector for this purpose:
std::vector<MYSTRUCT *> v(100);
for (auto& pointer : v)
pointer = new MYSTRUCT(/*...*/); //initializating (writing address to pointer)
In your way you just initializing a object of pointer type. In other words you allocating memory only for pointer, where you must write address to your structure or nullptr-value.
Others have said similar things to this, but specifically I'd do it like this:
std::vector <MYSTRUCT *> vect;
for(int i = 0; i < 2; i++){
vect.push_back();
}
Then you can just access each element like an array, like vect[0]. Plus with std::vector you can access the first element (element 0) with vect.front() and the last with vect.back().
Though it's useless without assigning a MYSTRUCT that has been initialized separately, I can see the usefulness of struct * vectors.

C++ : Allocation of an array attribute in a class

I would like to know, if I have a class with an array attribute whose size is not the same for all instances :
class myObject{
private:
int size;
int* array;
// other methods/attributes
};
Is it obligatory allocated using new ?
explicit myObject(int size = 0):size(size){
array = new int[size];
}
Even if in the main(), I always use constant parameters to create the instances of the class ? (Meaning I know every array size at compile time).
int main{
myObject object (5);
return 0;
}
Apparently something like :
private:
int size;
int array[size];
wont work, no ?
That means that array attribute whose size are not constant of the class are obligatory on the heap ?
Thank you for your answers,
That class contains no array. What you called array is a pointer; you cannot store any ints in it. If you really do just store a pointer, you'll have to allocate the memory yourself somehow; it can't magically appear. You'll also have to deallocate it yourself, and make sure that copying and assigning myObject objects doesn't cause any issues.
However, it's unlikely that a pointer is really the best way to do things. The standard library provides the std::vector class template which lets you use almost exactly the syntax you want:
class myObject {
std::vector<int> vector;
public:
myObject() {};
explicit myObject(std::size_t n) : vector(n) {}
};
With this in place you can create myObjects and they'll have the right amount of storage ready for them. It'll likely be dynamically allocated using operator new[], just like if you'd do it manually, but you don't have to worry about copying or deleting it.
int main() {
myObject a; // default-constructed, vector is empty.
myObject b(10); // std::size_t constructor, vector has 10 elements.
} // scope exit, b and a destroyed.
You can use the vector member much like if it was an array; the only thing it does not support is implicit decay to pointer, but the data member function makes up for even that.
As an alternative, if you always know the size at compile-time you can change the class into a class template and make the size a template parameter:
template<std::size_t N>
class myObject{
std::array<int, N> array;
// other methods/attributes
};
However, note that you now cannot use myObject<10> to a function expecting myObject<20>.
It is unlikely that you want more control than the above possibilities provide -- std::vector can be given an allocator, so it can do almost all work for you -- you could use std::unique_ptr<int[]> and make_unique together to make things work for you. However, if you need this kind of power, you probably know it yourself.
As a closing note, if you're just learning C++ and your book doesn't cover std::vectors somewhere early on, perhaps it's best to get a different book; they're one of the most commonly-useful data structures in the standard library and definitely not something to be left in an appendix.
If you need a variable sized array as a member of a class, don't use built-in arrays directly. Instead, use std::vector<T>, e.g.:
class myObject {
std::vector<int> array;
public:
explicit myObject(int size = 0): array(size){}
};
You can get the std:vector<int>'s size using array.size(), i.e., there is no need to store the size separately. Also, the content is automatically default initialized.