Search code examples
c++oopdesign-patternsgarbage

In C++ OOP, who is responsible to delete object passed to constructor


For example,

I have an account generator class need a random method to decide username and password. Random has many ways to implement, so it is an interface with many subclass. Account generator class accept Random object in constructor.

In Java we don't care the deletion of object. But I'm now doing it in C++. My question is, if I did the following in main()

Random random=new StdRandom();
AccGen accGen=new AccGen(random);

should I delete "random" in main(), or I should put it in the destructor of AccGen?

Edit:

Even after the question is being answered very well, I think I may still state the reason that why do I use pointer, in order to help somebody facing the same problem.

The reason I use pointer, is to apply many patterns like Factory and Behavior. Non-pointer variable seems not able to be an Interface with pure virtual method, which cannot present overrides.

In a design view, I think the creator of an object is always responsible for its deletion. That is why it makes me confused. All the caller wants, it an AccGen object. I passed a random object is to decide the implementation of Random, inside AccGen. Then Random object is not a participant in caller's level, then why should the caller be responsible for its deletion. But the fact is, in some case, the random is useful in the following actions in caller's level. The given example is really just an example.

After a study of smart pointer, Unique pointer really is the solution of my problem. It makes pointer become more specific, in terms of to state the purpose of creating such pointer.

To summarize, if an object is useful after passed to constructor, then the type would be pure pointer and with no deletion in destructor. If the object is useless in caller's level, then the type should be unique pointer.


Solution

  • My question is, if I did the following in main()

    Random random=new StdRandom();
    AccGen accGen=new AccGen(random);
    

    The thing is: You dont. Random is a not a pointer type (unless it is a misleading alias for SomeOtherType*) but new returns you a pointer to the object it creates.

    If you need dynamic allocations you can do it manually with raw pointers and take the full responsibility of deleteing things you created via new:

    Random* random = new StdRandom();
    AccGen* accGen = new AccGen(random);
    // ... do something ...
    delete accGen;
    delete random;
    

    It helps to get acustomed to the concept of ownership. If one object is responsible to manage the lifetime of a second instance, it is said to "own" that instance.

    Further, resources are acquired in the constructor and released in the destructor (read about RAII if you want to know more). Hence, you could consider to let accGen take responsibility for deleting random in its destructor (*).

    Doing this manually is neither recommended nor necessary. Use smart pointers. You can forget about new and delete if you just let smart pointers do the dirty work. There is no garbage in C++, though consistently using std::shared_ptr is probably what is closest to using a garbage collector.

    Anyhow, if you do not need to allocate memory dynamically, then do not. C++ has value semantics. In C++ you get more than just references to objects, you get the objects.

    int main {
        StdRandom random;
        AccGen accGen{random};
        // ... use accGen ...
    }   // <- end of scope
    

    No need to delete anything. Objects on the stack get their destructor called when going out of scope.

    (*) = If a function gets passed a raw pointer, it is not expected to take ownership of the pointed to object. The function cannot know if it is allocated on the stack or dynamically.