C++ Class array memory reallocation - c++

I'm sorry if this question as already been asked but I have no idea how to word this right.
So I'm building an application which needs to be really memory efficient since its on an Arduino Uno (2kbyte sram) and cant load a full array of class objects I need, so I decided to load it in parts.
This is basically how I plan to do it:
//declare class object array
MyClass objects[10];
objects[0] = MyClass(*parameters for initializing*);
....
....
//Some code with objects
//now changing the objects
objects[0] = MyClass(*parameters for initializing*);
Now my question is will the first objects[0] memory be freed when I change object[0] to the other value?
As far as I understand an object is basically a pointer to the fields of the class and when calling a constructor you get a new pointer to a object, so what I'm doing in the code is changing what objects[0] is pointing at but I'm not sure the first pointed at value of objects[0] memory gets freed.

As far as I understand an object is basically a pointer to the fields of the class and when calling a constructor you get a new pointer to a object[.]
No, in C++ an object is... well, an actual object. MyClass objects[10] is made of ten MyClasses side-by-side, no pointer involved.
When you write objects[0] = MyClass(/* ... */);, you are constructing a new MyClass, then assigning (copying) it to the first MyClass in the array, then destroying it. Again, no pointer involved.

Now my question is will the first objects[0] memory be freed when I change object[0] to the other value?
No. Throughout the lifetime of the array, the 10 objects are the same. No objects are ever added or removed. The memory of all the objects (not counting dynamic memory that they may own) is allocated when the lifetime of the array begins, and freed when the lifetime of the array ends.
When you assign to one member of the array, the copy (or move) assignment operator changes the state of the object within the array. The temporary object that was copied from, is destroyed at the end of the assignment.
As far as I understand an object is basically a pointer to the fields of the class
That seems misleading to me. A better analogy is that an object is a block of memory, and the member objects are sub-objects within that memory block. Just like array is a block of memory, and members of the array are sub objects within that memory block.
Your pointer analogy would be appropriate in some languages like Java where non-primitive variables are implicitly pointers. But not in languages like C++, where pointers are explicit, and value semantics are used implicitly.

Related

Can i delete a statically defined variable using delete operator? [duplicate]

I have an object with a vector of pointers to other objects in it, something like this:
class Object {
...
vector<Object*> objlist;
...
};
Now, Objects will be added to list in both of these ways:
Object obj;
obj.objlist.push_back(new Object);
and
Object name;
Object* anon = &name;
obj.objlist.push_back(anon);
If a make a destructor that is simply
~Object {
for (int i = 0; i < objlist.size(); i++) {
delete objlist[i];
objlist[i] = NULL;
}
}
Will there be any adverse consequences in terms of when it tries to delete an object that was not created with new?
Yes, there will be adverse effects.
You must not delete an object that was not allocated with new. If the object was allocated on the stack, your compiler has already generated a call to its destructor at the end of its scope. This means you will call the destructor twice, with potentially very bad effects.
Besides calling the destructor twice, you will also attempt to deallocate a memory block that was never allocated. The new operator presumably puts the objects on the heap; delete expects to find the object in the same region the new operator puts them. However, your object that was not allocated with new lives on the stack. This will very probably crash your program (if it does not already crash after calling the destructor a second time).
You'll also get in deep trouble if your Object on the heap lives longer than your Object on the stack: you'll get a dangling reference to somewhere on the stack, and you'll get incorrect results/crash the next time you access it.
The general rule I see is that stuff that live on the stack can reference stuff that lives on the heap, but stuff on the heap should not reference stuff on the stack because of the very high chances that they'll outlive stack objects. And pointers to both should not be mixed together.
No, you can only delete what you newed
Object* anon = &name;
When name goes out of scope, you will have an invalid pointer in your vector.
What you're actually asking is whether it's safe to delete an object not allocated via new through the delete operator, and if so, why?
Unfortunately, this is obfuscated by some other problems in your code. As mentioned, when name goes out of scope, you're going to end up with an invalid pointer.
See zneak's answer for why your original question doesn't result in a safe operation, and why the scope for name actually matters.
This will not work - if you delete an object that wasn't allocated by new you've violated the rules or the delete operator.
If you need to have your vector store objects that may or may not need to be deleted, you'll need to keep track of that somehow. One option is to use a smart pointer that keeps track of whether the pointed to object is dynamic or not. For example, shared_ptr<> allows you to specify a deallocator object when constructing the shard_ptr<> and as the docs mention:
For example, a "no-op" deallocator is useful when returning a shared_ptr to a statically allocated object
However, you should still be careful when passing pointers to automatic variables - if the vector's lifetime is longer than the lifetime of the variable then it'll be refering to garbage at some point.

Creating objects in c++

I just waste hours on a simple line causing data loss. I have AnotherClass holding a vector of instances of MyClass. This AnotherClass instantiates objects of MyClass the following way:
AnotherClass::AnotherClass(){
MyClass myObject(...);
myVector.push_back(&myObject);
}
The address of myObject is afterwards pushed into a vector (with other instances of MyClass), like written in the code. When I start using instances of AnotherClass I notice the values of MyClass were lost (completely random). When I change the code to:
AnotherClass::AnotherClass(){
MyClass* myObject = new MyClass(...);
myVector.push_back(myObject);
}
I don't have data loss.
Can somebody be so kind to explain me why the second way of creating objects doesn't lead to a loss of data? (without referencing me to books of 1.000 pages)
Simple. The first version creates a local variable on the stack, which gets destroyed automatically when it goes out of scope (at the end of the function)
Your vector just contains a pointer to where the object used to be.
The second version creates an object on the heap, which will live until you eventually delete it.
The reason is RAII.
In the first snippet you declare an object in the scope of your method/constructor.
As soon this scope ends, this is the case when method is finished, your object gets out-of-scope and becomes cleaned for you (this means that its desctructor is called). Your vector now still holds pointers to your already cleaned and thus invalid objects, thats the reason why you get garbage.
In the second snippter, your object are contained on the heap. They wont become cleaned / destroyed unless you call delete myObj;. Thats the reason why they remain valid even after the method has finsihed.
You can solve this on multiple ways:
Declare your vector as std::vector<MyClass> (notice, not a pointer type)
Keep your second snippet but make sure to delete all elements of your vector once your done
Use smart pointers if you dont want to cleanup your objects by your own (e.g std::shared_ptr or std::unique_ptr)
The first way allocates a MyClass object on the stack. That object will be deallocated the moment it goes out ofscope, I.e. when the constructor has run its course.
The second way allocates the object in dynamic memory. That object will continue to exist until you call delete on it.
The second way is the way to do it but you should add a destructor to AnotherClass that iterates through the vector and deletes all objects. Otherwise your program will have a memory leak.

Pointer Ownership

I have an array of pointers: pArray[rows][columns], where each element can contain a pointer to an object. Some of the objects were instantiated in main() on the heap, and some were instantiated by objects themselves also on the heap: That is, I passed pArray to an object member function, and that function created a new object, and put a pointer to it in pArray.
Now when I want to delete pointers to objects from pArray, is there ownership in play here? Meaning, if an object created a new object and placed a pointer to it in pArray, can only the creator object call delete on that pointer? Or can I do it from main(), and other objects by passing the array to them?
Some more details:
The code simulates a predator prey model on a grid (pArray). So I begin by reading in the initial grid config from a file, and instantiate objects (predators, and prey), on pArray from main(). But predators and prey can breed, so objects spawn new objects and by passing pArray to them, they instantiate their children on pArray.
With raw pointers ownership is purely a concept. As long as you are working with raw pointers, it is entirely up to you to assign ownership of pointed object to anyone and anything. It is a matter of your design. There's no such "rule" that the object should be deleted by whoever created them. Ownership can be retained or passed on. Ownership can be shared (as in reference-counted ownership schemes). Again, it is a matter of your design and your intent.
Various smart pointer classes will help you to express your intent and implement your intent. With raw pointers you have to remember who owns what and do everything manually.
No, there is no "ownership" on pointers in C++, if the pointer is valid (contains proper reference to data / object), you can deallocate it anywhere issuing delete command.
The destructor of objects is subject to the same public/protected/private like every other method. So, if the destructor is public, anyone can call delete on the object.
The only important thing is that it happens exactly once, and only after nobody is using the object anymore.
There is no ownership concept for pointers in C++ .As far as I understood your question, Yes you can delete that object from main() in case of dynamic memory allocation. The memory allocated to that object would only be freed only when the program ends or the Object array goes out of scope and the destructor for the class is called.

How to allocate heap pointer

Lets say I have a object whose purpose is to hold a bunch of pointers for an object type MyObject, and lets say I want a function that adds new MyObjects to the collection like so:
void MyCollection::addObject(){
MyObject *newObject = new MyObject();
MyCollection.add(mycollection, newObject);
}
Lets say that MyCollection.add takes in a particular collection object and a pointer and somehow internally stores it. However the problem with this function is while the newObject itself is persistent, the *newObject pointer gets destroyed after the function call so the add() function no longer has a pointer that really points to the object. Is there any good way to make a persistent pointer somehow?
Thanks
However the problem with this function is while the newObject itself
is persistent, the *newObject pointer gets destroyed after the
function call so the add() function no longer has a pointer that
really points to the object.
This betrays a huge misunderstanding about how objects and pointers work.
A pointer is an address. new creates an object on the heap and returns the address. When you pass that address to the collection the collection gets a copy of the address, which is exactly the same as the address you got from new. When the variable newObject goes out of scope and is destroyed, the collection still has the copy of the address, and the address still points to the object. No matter how many copies of the address you make and destroy, the address is still good and the object that the address points to is still good.
In fact, the address you get back from new is a copy of the address that new generated internally, and that original, internal value is destroyed. And when you say MyObject *newObject = new MyObject(); you're making another copy. But it doesn't matter because every copy of the address is as good as every other one.
Stack-based data -- like your pointer -- doesn't get "destroyed", per se. The variable itself goes out of scope, but the data it contained -- i.e., the address of the MyObject object -- is still totally valid. If the add() method copies the value of the pointer, all will be good.
Incidentally, I hope that the implementation of add() is just
myVector.push_back(newObject);
where myVector is an instance of std::vector. No need to reinvent the wheel!
The code as written is fine. The pointer will be (must be) copied by the add() method, whose signature is presumably void add(MyObject*).
By the way, your C++ here is invalid:
MyCollection.add(mycollection, newObject);
It should probably be:
mycollection.add(newObject);
This is not a problem. A well defined add function will make a copy of the pointer, so the original pointer going out of scope won't cause any issues.

New Object variations

This is a very newbie question, but something completely new to me. In my code, and everywhere I have seen it before, new objects are created as such...
MyClass x = new MyClass(factory);
However, I just saw some example code that looks like this...
MyClass x(factory);
Does that do the same thing?
Not at all.
The first example uses dynamic memory allocation, i.e., you are allocating an instance of MyClass on the heap (as opposed to the stack). You would need to call delete on that pointer manually or you end up with a memory leak. Also, operator new returns a pointer, not the object itself, so your code would not compile. It needs to change to:
MyClass* x = new MyClass(factory);
The second example allocated an instance of MyClass on the stack. This is very useful for short lived objects as they will automatically be cleaned up when the leave the current scope (and it is fast; cleaning up the stack involves nothing more than incrementing or decrementing a pointer).
This is also how you would implement the Resource Acquisition is Initialization pattern, more commonly referred to as RAII. The destructor for your type would clean up any dynamically allocated memory, so when the stack allocated variable goes out of scope any dynamically allocated memory is cleaned up for you without the need for any outside calls to delete.
No. When you use new, you create objects off the heap that you must then delete later. In addition, you really need MyClass*. The other form creates an object on the stack that will be automatically destroyed at end of scope.