-1

I created simple code with 2 classes.

#include <list>
#include <iostream>

using namespace std;

class MyItem {
        public:
                int myVar;
                MyItem() {
                        this->myVar = 10;
                }
                ~MyItem(){
                }
};

class Container {
        public: 
                list<MyItem*> items;
                Container() {
                }
                ~Container(){
                        for (auto *item: this->items) {
                                delete item;
                        }
                }
                void addItems(MyItem* item) {
                        this->items.push_back(item);
                }
};


int main() {
        MyItem* i1 = new MyItem();
        MyItem* i2 = new MyItem();
        MyItem* i3 = new MyItem();
        cout << i1->myVar << endl;

        Container* c1 = new Container();
        c1->addItems(i1);
        c1->addItems(i2);
        c1->addItems(i3);

        delete c1;

        cout << i1->myVar << endl;
        cout << i2->myVar << endl;
        cout << i3->myVar << endl;
}

And without virtual ~MyuItem() in MyItem class I get output as expected:

10 <- myVar before deconstructor
0  <- memory garbage
28802064
28802096

But when I change code to:

virtual ~MyItem(){
}

The output looks different:

10
10
10
10

Why I can still access dereference values from instances that should not point to memory with data? I don't understand how virtual destructor can affect it. Or there is other mistake that I cannot find. Am I something missing?

And yes I want to delete it in my container class destructor. Just because I want to understand how it works on raw pointers. I know that I should use smart pointers because they will automatically deallocate memory.

A. Dziedziczak
  • 193
  • 3
  • 12
  • 2
    Short answer: Undefined behavior is undefined. Long answer: one moment, let me find a duplicate. – Algirdas Preidžius Jan 12 '18 at 01:17
  • Allright so with `virtual ~MyItem()` result is still garbage from memory. Thanks ;) I just wanted to be sure because the only thing I changed was this destructor. I didn't think that this was undefined behavior. Thanks ;) – A. Dziedziczak Jan 12 '18 at 01:23
  • Well, `10` is just as valid garbage value as any other. If it so happens, that it was the same value your field was set to - it's just a coincidence. :) Or to be more precise: most likely reason for this behavior is that C++ is mostly about performance. Overwriting a memory with some pattern, on delete, would take some time, so it just isn't done, leaving what was located in memory - unchanged, and since you didn't do any other memory allocations between deletes, and value access - the memory didn't have the opportunity to be changed. – Algirdas Preidžius Jan 12 '18 at 09:11

1 Answers1

2

Accessing a deleted object is undefined behavior, nothing says that the library has to clear the memory, it can or it may not. What you are doing is something you can not count on working despite the fact that it happens to in this instance.

SoronelHaetir
  • 14,104
  • 1
  • 12
  • 23
  • Well I stil don't understand how on three different computers the output is this same for virtual constructor but if you say that's undefined garbage then I will accept your answer. I just could not belive that on three computers output for that simple change was this same. Thanks ;) – A. Dziedziczak Jan 12 '18 at 01:26
  • 1
    you are getting the same garbage because you are not getting random memory locations, you are just getting memory that was reassigned to the something else and that something else is the same every time, like the output buffers for the cout or whatever. Change the code a bit (read a file between the release and the cout)and rerun it , you will get different output – pm100 Jan 12 '18 at 01:27