Search code examples
c++pointersstructnew-operatordelete-operator

On deleting C++ pointers


OK..so this confuses the hell out of me. I am dealing with some legacy C++ code parts of which I have a feeling are just not safe, but I am not 100% sure. Here's a snippet, for example of the risky stuff.

struct A {
    A() : a_ptr(0) {}
    A(some_type *ptr) : a_ptr(ptr) {}
    const some_type *a_ptr;
};

struct B {
    B() : b_ptr(0) {}
    B(some_type *ptr) : b_ptr(ptr) {}
    const some_type *b_ptr;
};

struct Data {
    Data(...) {//-Stuff that doesn't invole aptr_list or bptr_list;
    }
    ~Data() {
        for(std::vector<A*>::iterator itr = aptr_list.begin(); itr != aptr_list.end() ++itr) {
            delete *itr;
        }
        for(std::vector<B*>::iterator itr = bptr_list.begin(); itr != bptr_list.end() ++itr) {
            delete *itr;
        }
    }
    std::vector<A*> aptr_list;
    std::vector<B*> bptr_list;
private:
    Data(const Data&);
    Data& operator=(const Data&);
};

Then in the implementation, I find:

void some_func(...) {
    //-Inside some function
    Data& d = get_data(...);
    ...
    for(...) {
         some_type *sptr = dynamic_cast<some_type*>(a_source_of_some_type_pointer);
         A* a = new A(sptr);
         B* b = new B(sptr);
         d.aptr_list.push_back(a);
         d.bptr_list.push_back(b);
    }
}

I am a little uneasy about the same pointer sptr being used in the implementation above; would this create problems when the destructor of Data is invoked? On the other hand, it looks like we have two new calls for A* and B* and exactly two deletes, so if the destructor in Data is not deep - and maybe that's where I need clarification, then perhaps this is safe after all and my concern is misplaced? I did notice that the structs A and B for instance don't have any destructors defined, so I hope it is not deep. But I am not sure if this means their pointer data will be freed up or not. Appreciate expert insights as always.

Thanks for your time and interest.


Solution

  • A and B do not have a user defined destructor, so nothing INSIDE a or b gets destroyed (other than the actual memory it holds being freed up, but since sptr is just held there, it is not being deleted). [Obviously, if A or B contains some other class, say a std::string or a std::vector, that class would be destroyed].

    So, in other words, your code is just fine like it is - a and b only holds a copy of sptr, but it's never deleted [in this bit of code, if it needs deleting later, that's a different matter].