C++ polymorphic class pointer in vector - c++

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.

Related

Delete Inherited class Pointer Array in 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.

c++ - Reference Counting garbage collection

Consider a simple class:
class MyInt {
public:
MyInt();
MyInt(const char *num);
};
I want to intergrate reference counting design pattern in to the class, which means i need to keep track of how much pointers point to an instance of this class. I need to implement it in this class only or create a different class and inherit it.
Given this example code i want to clear any allocated memory of the program:
int main() {
MyInt*a = new MyInt("10");
a = new MyInt("20");
delete a;
return 0;
}
My Tries
I tried operator oveloading of '=' and adding referenceCount member:
MyInt &MyInt::operator=(const MyInt* right) {
MyInt*left = this;
*this = right;
left->referenceCount -= 1;
if (left->referenceCount == 0) {
delete (left);
}
return *this;
}
But this does not work because we assign pointer of the class to another pointer.
Also tried to override the new and delete operators but can't seem to make it work and keep track of the number of pointer to an instance.
As it seems i need to implement four things: copy constructor, operator new, operator delete and operator =.
How can i effectivly keep track of the pointers and clear unpointed memory automaticly?
std::shared_ptr does exactly this. From the ref:
Manages the storage of a pointer, providing a limited
garbage-collection facility, possibly sharing that management with
other objects. [...] Once all shared_ptr objects that share ownership
over a pointer have released this ownership, the managed object is
deleted.
so I suggest you use this instead.
a is a pointer, so assigning to a will not involve MyInt::opterator= in any way. There is no way to detect when a pointer to T is assigned to by overloading T's operators. To do this, you would need to design a class type that behaves like a pointer. Then you could properly track when the pointer might leak an object and properly delete it. Fortunately for you, the standard library already provides this class. It's std::shared_ptr. Here is your example modified to use std::shared_ptr :
#include <memory>
struct InfInt {
InfInt(const char *) {}
};
int main()
{
auto a = std::make_shared<InfInt>("10");
a = std::make_shared<InfInt>("20"); // the previous `a` is deleted
// The object pointed to by `a` is automatically deleted when
// the last reference to it goes out of scope
return 0;
}

Derived class memory leak

I'm trying to figure out the memory leaks that I'm having.
I have these (simplified) classes (can not be changed, I have to work with these):
class Base
{
bool baseBool;
Base(Base&){};
virtual ~Base();
}
class Derived1 : public: Base
{
char* text;
Derived1(Derived1&);
~Derived1();
}
class Derived2 : public: Base
{
int num;
Derived2(Derived2&);
~Derived()
}
Derived1 Copy constructor
Derived1::Derived1(Derived1& derived):text("")
{
text=new char[strlen(text)+1]; //assign enough memory + 1
strcpy(text,derived.text); //copy existing aText into new objects aText
}
Then I have a struct used to manipulate them
struct Container
{
Container& operator=(Container&);
Base** bases
}
In the overloaded operator= for struct Container I'm making a deep copy of the Container objects. Like so:
Container& Container::operator=(Container& R)
{
int i,j,k;
for(i=0;i<MAX;i++)
delete bases[i];
delete[]bases;
bases=new Base*[MAX];
for(j=0;j<MAX;j++)
answers[j]=0;
for(k=0;k<MAX;k++)
{
if(dynamic_cast<Derived1 *>(R.bases[k]))
bases[k]=new Derived1(*(dynamic_cast<Derived1 *>(R.bases[k])));
else
bases[k]=new Derived2(*(dynamic_cast<Derived2 *>(R.bases[k])));
}
return *this;
}
This part of the code works if I were to assign a newly created Container object using the overloaded = operator
Like so in my main
Container containers[2];
bases = new Base*[2];
bases[0] = new Derived1("boooo");
bases[1] = new Derived2(3);
containers[0]=*(new Container(bases)); //uses the overloaded operator= OK
But if I were to assign two already made Container objects to each other like so:
containers[0]=containers[1];
Following debugging it crashes on
for(i=0;i<MAX;i++)
delete bases[i];
Saying
HEAP[ass3.exe]: Heap block at 00729268 modified at 00729295 past requested size of 25
ass3.exe has triggered a breakpoint.
HEAP[ass3.exe]: Invalid address specified to RtlValidateHeap( 00720000, 00729270 )
ass3.exe has triggered a breakpoint.
Which is why I think I have memory leaks because Derived1 has a char*.
Glad for any input.
Thanks! I hope I was clear enough...
Edit: I do have an empty base copy constructor, and the derived cc does exist as well. Maybe I went to simple for the example.
It looks like MAX is a number greater than the size of bases ie. bases may only have 5 entrys while MAX could be 10. In this case, once you get past the end of bases (bases[5] does not exist if the size is only 5 because the numbering starts at 0). I typically use a vector instead of an array and my code for the for loop would look like this:
for(i=0;i<bases.size();i++)
delete bases[i];
This ensures that your for loop does not go past the end of bases.
From the example, you've given you need to make sure that the 'bases' member of struct Container itself is actually allocated, and initialized.
From the symptoms you've expressed (crashing on the first iteration), it looks like you're deleting an un-initialized bases pointer (array of pointers), or the actual pointers themselves are not being properly nullptr initialized.
This may be down to your sample code being incomplete however.

C++: Inside a method can one create an uninitialised object from the class?

Inside a method can one create an uninitialised object from the class?
Here's some context: imagine a class where the constructors all allocate memory:
class NumberArray
{
size_t m_Size;
int *m_Numbers;
public:
NumberArray() { m_Size = 1; m_Numbers = new int[1]; m_Numbers[0] = 0; }
// . . . other methods for manipulating or constructing . . .
~NumberArray() { delete[] m_Numbers; }
// What if I had a method that concatenates two arrays?
NumberArray ConcatenateWith(const NumberArray &) const;
};
Inside such a method one would desire to create an uninitialised object of class NumberArray, and then 'construct' a new object based on this and the object in the parameter? AKA:
NumberArray NumberArray::ConcatenateWith(const NumberArray &other) const
{
// Mystery manner of creating an uninitialised NumberArray 'returnObject'.
returnObject.m_Size = m_Size + other.m_Size;
returnObject.m_Numbers = new int[returnObject.m_Size];
std::copy(m_Numbers, m_Numbers + m_Size, returnObject.m_Numbers);
std::copy(other.m_Numbers, other.m_Numbers + other.m_Size, returnObject.m_Numbers + m_Size);
return returnObject;
}
What's the best way of doing this? Basically, I don't want the default constructor to create a size 1 array that I will just delete and then allocate a new array for again anyway.
It's not entirely clear what you are trying to do, but if all you want is to create a new instance of the class and not have a constructor other than the default constructor called then do just that.
All you have to do is create a private constructor, that has a different signature from the default constructor and which does not allocate memory (or differs in whatever way you need it to differ from the default constructor); then simply have your class invoke that constructor internally, when necessary.
What you're asking for is placement new. This looks something like this:
#include <cstdlib>
#include <new>
void* mem = std::malloc(sizeof(T)); // memory for a T (properly aligned per malloc)
T* x = new (mem) T; // construct a T in that memory location
x->~T(); // destruct that T
std::free(mem); // and free the memory
Doing this correctly (in an exception-safe manner with properly managed and aligned memory) is not a trivial task. You need to be careful about the lifetime of your objects.
For your question, you are describing exactly what std::vector does. It allocates raw uninitialized memory and constructs inserted elements directly into that memory. And lots of its code is dedicated to just getting the lifetime and memory management correct and exception safe!
You should strongly prefer to use std::vector instead of writing it yourself.
There is no well-defined way, as far as I'm aware, to create an object without invoking it's constructor. This is regardless of whether you have access to its public interface or not, though you could implement a private or protected constructor if you want to restrict who can invoke it. There is otehrwise no restrictions on creating new instances of a class from its own internal methods, in fact it is quite common to define a private constructor and a static public method that create instances of said object if you want to restrict under which conditions said object can be created.
If you want to, you can allocated sufficient memory for an object and reinterpret_cast a pointer to that memory to a pointer of the type you want. This usually works for POD's, but since many implementations (if not all) of polymorphic inheritance in c++ adds a pointer to a vtable to polymorphic instances this approach will usually, if not always, fail for those.
In short, create a private constructor and have a static method invoke it and then do any other work that you need is my recommendation.
I think this may be similar to what you want, an 'anonymous' class of sorts:
struct test {
virtual void doSomething() {
puts("test");
}
};
struct a {
test *t() {
struct b : test {
void doSomething() {
puts("b");
};
};
return new b;
};
};
int main()
{
a a;
a.t()->doSomething(); // outputs 'b'
}
However, due to slicing and how new works on C++, you must return a pointer and the 'anonymous' type must have a name, even if it's restricted only to the function.
If you could edit the OP and clarify exactly what you wish to accomplish by this, maybe we could help you more.

C++ question about setting class variables

I'm not new to programming, but after working in Java I'm coming back to C++ and am a little confused about class variables that aren't pointers. Given the following code:
#include <iostream>
#include <map>
using namespace std;
class Foo {
public:
Foo() {
bars[0] = new Bar;
bars[0]->id = 5;
}
~Foo() { }
struct Bar {
int id;
};
void set_bars(map<int,Bar*>& b) {
bars = b;
}
void hello() {
cout << bars[0]->id << endl;
}
protected:
map<int,Bar*> bars;
};
int main() {
Foo foo;
foo.hello();
map<int,Foo::Bar*> testbars;
testbars[0] = new Foo::Bar;
testbars[0]->id = 10;
foo.set_bars(testbars);
foo.hello();
return(0);
}
I get the expected output of 5 & 10. However, my lack of understanding about references and pointers and such in C++ make me wonder if this will actually work in the wild, or if once testbars goes out of scope it will barf. Of course, here, testbars will not go out of scope before the program ends, but what if it were created in another class function as a function variable? Anyway, I guess my main question is would it better/safer for me to create the bars class variable as a pointer to the map map?
Anyway, I guess my main question is
would it better/safer for me to create
the bars class variable as a pointer
to the map map?
No. C++ is nothing like Java in this and may other respects. If you find yourself using pointers and allocating new'd objects to them a lot, you are probably doing something wrong. To learn the right way to do things, I suggest getting hold of a copy of Accelerated C++ by Koenig & Moo,
The member variable bars is a separate instance of a "dictionary"-like/associative array class. So when it is assigned to in set_bars, the contents of the parameter b are copied into bars. So there is no need to worry about the relative lifetimes of foo and testbars, as they are independent "value-like" entites.
You have more of a problem with the lifetimes of the Bar objects, which are currently never going to be deleted. If you add code somewhere to delete them, then you will introduce a further problem because you are copying the addresses of Bar objects (rather than the objects themselves), so you have the same object pointed to by two different maps. Once the object is deleted, the other map will continue to refer to it. This is the kind of thing that you should avoid like the plague in C++! Naked pointers to objects allocated with new are a disaster waiting to happen.
References (declared with &) are not different from pointers with regard to object lifetimes. To allow you to refer to the same object from two places, you can use either pointers or references, but this will still leave you with the problem of deallocation.
You can get some way toward solving the deallocation problem by using a class like shared_ptr, which should be included with any up-to-date C++ environment (in std::tr1). But then you may hit problems with cyclical pointer networks (A points to B and B points to A, for example), which will not be automatically cleaned up.
For every new you need a corresponding delete.
If you try and reference the memory after you call delete - where ever that is - then the program will indeed "barf".
If you don't then you will be fine, it's that simple.
You should design your classes so that ownership of memory is explicit, and that you KNOW that for every allocation you are doing an equal deallocation.
Never assume another class/container will delete memory you allocated.
Hope this helps.
In the code below you can pass map of Bars and then will be able to modify Bars outside of the class.
But. But unless you call set_bars again.
It is better when one object is responsible for creation and deletion of Bars. Which is not true in your case.
If you want you can use boost::shared_ptr< Bars > instead of Bars*. That will be more Java like behavior.
class Foo {
public:
Foo() {
bars[0] = new Bar;
bars[0]->id = 5;
}
~Foo() { freeBarsMemory(); }
struct Bar {
int id;
};
typedef std::map<int,Bar*> BarsList;
void set_bars(const BarsList& b) {
freeBarsMemory();
bars = b;
}
void hello() {
std::cout << bars[0]->id << std::endl;
}
protected:
BarsList bars;
void freeBarsMemory()
{
BarsList::const_iterator it = bars.begin();
BarsList::const_iterator end = bars.end();
for (; it != end; ++it)
delete it->second;
bars.clear();
}
};
I'm not new to programming, but after working in Java I'm coming back to C++ and am a little confused about class variables that aren't pointers.
The confusion appears to come from a combination of data that is on the heap and data that is not necessarily on the heap. This is a common cause of confusion.
In the code you posted, bars is not a pointer. Since it's in class scope, it will exist until the object containing it (testbars) is destroyed. In this case testbars was created on the stack so it will be destroyed when it falls out of scope, regardless of how deeply nested that scope is. And when testbars is destroyed, subobjects of testbars (whether they are parent classes or objects contained within the testbars object) will have their destructors run at that exact moment in a well-defined order.
This is an extremely powerful aspect of C++. Imagine a class with a 10-line constructor that opens a network connection, allocates memory on the heap, and writes data to a file. Imagine that the class's destructor undoes all of that (closes the network connection, deallocates the memory on the heap, closes the file, etc.). Now imagine that creating an object of this class fails halfway through the constructor (say, the network connection is down). How can the program know which lines of the destructor will undo the parts of the constructor that succeeded? There is no general way to know this, so the destructor of that object is not run.
Now imagine a class that contains ten objects, and the constructor for each of those objects does one thing that must be rolled back (opens a network connection, allocates memory on the heap, writes data to a file, etc.) and the destructor for each of those objects includes the code necessary to roll back the action (closes the network connection, deallocates objects, closes the file, etc.). If only five objects are successfully created then only those five need to be destroyed, and their destructors will run at that exact moment in time.
If testbars had been created on the heap (via new) then it would only be destroyed when calling delete. In general it's much easier to use objects on the stack unless there is some reason for the object to outlast the scope it was created in.
Which brings me to Foo::bar. Foo::bars is a map that refers to objects on the heap. Well, it refers to pointers that, in this code example, refer to objects allocated on the heap (pointers can also refer to objects allocated on the stack). In the example you posted the objects these pointers refer to are never deleted, and because these objects are on the heap you're getting a (small) memory leak (which the operating system cleans up on program exit). According to the STL, std::maps like Foo::bar do not delete pointers they refer to when they are destroyed. Boost has a few solutions to this problem. In your case it's probably be easiest to simply not allocate these objects on the heap:
#include <iostream>
#include <map>
using std::map;
using std::cout;
class Foo {
public:
Foo() {
// normally you wouldn't use the parenthesis on the next line
// but we're creating an object without a name, so we need them
bars[0] = Bar();
bars[0].id = 5;
}
~Foo() { }
struct Bar {
int id;
};
void set_bars(map<int,Bar>& b) {
bars = b;
}
void hello() {
cout << bars[0].id << endl;
}
protected:
map<int,Bar> bars;
};
int main() {
Foo foo;
foo.hello();
map<int,Foo::Bar> testbars;
// create another nameless object
testbars[0] = Foo::Bar();
testbars[0].id = 10;
foo.set_bars(testbars);
foo.hello();
return 0;
}