Legion Daeth Legion Daeth - 1 year ago 80
C++ Question

How to use new and delete in this scenario

So I have a class

that has as its members a binary search tree and a hash table (for organizing data by different parameters). The way I designed the program to work was that
has an
add(aVendor& vendor)
function that takes a dummy vendor object created in main and produces a pointer (using new) that points to a vendor object which then is passed to the bst and hash table's

Within the bst and hash table, they use new to create a node that contains a pointer to a vendor object and the requisite linking pointers (next, left, right, etc.)

In summary a dummy data object goes to
aCollection::add(aVendor& vendor)
, and a pointer to
object (with the data inside it) is sent to the bst and hash table which then store that pointer in their own
objects they declared using

My question is, how should I use
to properly release the memory?
The bst and hash table share the pointers to the
object that was passed to them and they each have their own nodes to delete. I know I need to call
in the bst and hash table's
functions (to delete their respective nodes)
but how do I ensure that
that is created in
is deleted once and only once?

P.S. Is calling new in
even necessary? I figure the pointer needs to stay allocated so the data always exists.

The code is a bit verbose so I made a quick illustration of what is going on.
Illustration of program add function


Thanks to Ped7g's excellent explanation I figured out that since
should be the function deleting the pointers I needed to keep track of the pointers to be deleted. Going by his/her suggestion I decided to use a
to add all the pointers added to the program to a list, then I designed a while loop in the destructor that iterates through those pointers and
s them, thus preventing memory leaks stemming from
, here is the code I wrote to do so.

20 //Constructor function
22 aCollection::aCollection()
23 {
24 //allocates one instance of a hash table and bst
25 hashTable = new hashFunctions;
26 bst = new aBst;
28 //Creates a list to track ptrs
29 trackList = std::list<aVendor*>();
30 return;
31 }
33 //Destructor
34 aCollection::~aCollection()
35 {
36 //Destroys hashTable and bst
37 delete hashTable;
38 delete bst;
39 //Deletes vendor pointer objects
40 while(!trackList.empty())
41 {
42 delete trackList.front();
43 trackList.pop_front();
44 }
45 return;
46 }

In the add function I used this line of code to add the pointers to the list

84 trackList.push_front(vendorPtr);

And finally this is how I declared the list as part of

43 list<aVendor*> trackList;

Answer Source

Try to follow the "everything belongs somewhere" principle.

Only the owner of information handles new/delete (better to say "avoids new/delete as much as possible"), other subjects don't care, if they receive a pointer, they assume it's live trough the whole time of their processing - because that's the owner responsibility, if it gave the pointer away, it should be aware how [long] it will be used outside, and adjust it's strategy of new/delete to fulfil those needs. So they don't delete it.

In your case it depends a lot, whether you remove vendors often from the structure, or you only add vendors to it. If you remove vendors only absolutely rarely and huge performance penalty is allowed then, you can have std::vector<aVendor> vendors; (1) in aCollection, giving the bs and hash nodes only iterator (or pointer/index) to the vendor. In case vendor is removed from vector, all bs/hash nodes have to updated with fresh iterator (pointer/index) = performance penalty upon remove. Well, actually inserting vendors will invalidate iterators and pointers too, only indices would survive, so use indices then - which also makes quite clear, how bs/hash nodes care about delete of vendor (you don't delete index, makes no sense).

If you remove vendors often, a std::list is better choice, as inserting/removing does not invalidate iterators, so all the copies of iterators in bs/hash nodes will remain correct.

Overall it looks like you wrote your own implementation of std::* containers... any particular reason for that? (it's a good learning exercise, and in very rare cases the performance decision, but in such case you would end with completely different design, because what you have is as horrible as std::list performance wise ... otherwise in production code it's usually much more efficient to stick with standard containers and design implementation around them, as they have reasonably OK-ish performance, and you don't have to implement them, only use).

(1) avoids new/delete completely. If that way is not practical for you (aVendor default constructor is costly), use std::vector<aVendor *> vendors; with manual new/delete upon insert/removal of vendor.


"how do I ensure that aVendor that is created in aCollection is deleted once and only once?"

Well, you delete it just once, in aCollection.

It's not clear from the question, what is your problem (maybe you are struggling with detection when a vendor is deleted in all nodes, and you want to release it from aCollection then too? That's completely different question, and would require much more architecture insight into the app algorithm, to see if there's some good place to detect "dangling" vendor no more used by any node, triggering delete in aCollection).

edit: how to new/delete example:

live example

#include <iostream>
#include <list>
#include <string>

class Vendor {
    std::string name;
    Vendor(const std::string & name) : name(name) {}
    const std::string & getName() const { return name; }

// A bit pointless example how to handle naked new/delete.
class VendorList {
    std::list<Vendor *> vendors;

    // usually with neatly designed classes the std::list<Vendor>
    // would suffice, saving all the hassle with new/delete
    // (that's why this example is a bit pointless)

    // Also storing around iterators to internal list outside
    // of VendorList class feels quite wrong, that's a code smell.

    ~VendorList() {
        std::cout << "~VendorList() destructor called.\n";
        // release any remaining vendors from heap
        auto vendorIterator = vendors.begin();
        while (vendorIterator != vendors.end()) {
            auto toRemove = vendorIterator++;
        // release the (now invalid) pointers
        // at this point, whoever still holds iterator
        // to a vendor has a problem, it's invalid now.

    // stores vendor into collection of vendors
    // + data of vendor are allocated on heap by "new"
    // returns iterator pointing to the newly added vendor
    // (not a best choice for public API)
    std::list<Vendor *>::iterator addVendor(const Vendor & vendor) {
        Vendor * copyOnHeap = new Vendor(vendor);
        std::cout << "VendorList: adding vendor: "
            << copyOnHeap->getName() << std::endl;
        return vendors.insert(vendors.end(), copyOnHeap);

    // removes particular vendor from the list
    // to be used after the rest of application does not hold any iterator
    void removeVendor(std::list<Vendor *>::iterator vendor_iterator) {
        std::cout << "VendorList: releasing specific vendor: " <<
            (*vendor_iterator)->getName() << std::endl;
        // release the heap memory containing vendor's data
        delete *vendor_iterator;
        // remove the released pointer from list
        // at this point, whoever still holds iterator
        // to that vendor has a problem, it's invalid now.

    const std::list<Vendor *> & get() const {
        return vendors;


int main()
    VendorList vlist;
    auto v2iterator = vlist.addVendor(Vendor("v2"));
    for (auto vendorPtr : vlist.get()) {
        std::cout << "Vendor in list: " << vendorPtr->getName() << std::endl;

I'm not really happy about this example, as it feels wrong on many levels (like bad OOP design), but to make the API fit your purpose, the purpose would have to be known first.

So take this only as an example where new and delete belongs. (only once in VendorList, which is owner + responsible for managing these. Nobody else in app should use new/delete on Vendor, they should instead call the VendorList add/remove functions, and let the list to manage the implementation details (like where it is stored, and how many new/deletes are per vendor used).

Usually by designing your data classes lean, and avoiding naked pointers, you can avoid new/delete completely in C++ code. You can try to turn this example into std::list<Vendor> variant, the code will be simplified a lot (empty destructor code, as default would release the list), removal/insert only called on the list, etc.

You then handle the life cycle of data in memory by scope. Like in main you have VendorList vl;, as that instance of vendor list will be used trough whole life cycle of application. Or if you need it only during invoice processing, you can declare it inside processInvoices(), again as local variable, init it, and then forget about it. It will get released when you go out of scope of processInvoices().

Which will release all initialised Vendors, as they belong into VendorList. Etc..

So as long as you manage to design your classes with clear "belongs to" and "responsible for", you can get to a great lengths by using only local/member variables, not using new/delete/shared_ptr/etc... at all. The source will look almost like Java with GC, just shorter and faster, and you implicitly know when the release of particular data happens (when they go out of their scope).

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download