I have a factory that builds the objects with longest lifetime in my application. These have types, lets say, ClientA and ClientB, which depend on Provider (an abstract class with many possible implementations), so both clients have a reference to Provider as member.
According to the command-line arguments, the factory chooses one implementation of Provider, constructs it (with ‘new‘), and passes it to the constructors of both clients.
The factory returns an object that represents my entire app. My main function is basically this:
int main(int argc, char** argv) { AppFactory factory(argc, argv); App app = factory.buildApp(); return app.run(); }
And the buildApp method is basically this:
App AppFactory::buildApp() { Provider* provider = NULL; if (some condition) { provider = new ProviderX(); } else { provider = new ProviderY(); } ClientA clientA(*provider); ClientB clientB(*provider); App app(clientA, clientB); return app; }
So, when execution ends, destructors of all objects are called, except for the provider object (because it was constructed with ‘new‘).
How can I improve this design to make sure that the destructor of the provider is called?
EDIT: To clarify, my intention is that both clients, the provider and the App object to share the same lifetime. After all answers, I now think both clients and the provider should be allocated on the heap its references passed to the App object, which will be responsible for deleting them when it dies. What do you say?
It’s very simple with a shared ownership smart pointer:
Assuming the app object owns the clients, and the clients all share the one provider. Make the clients take a
shared_ptr<Provider>then, instead of aProvider&. As long as there is still a copy of a shared_ptr owning the provider object, the object won’t be freed.The best would be to not copy clientA and clientB, and not copy app by returning it by value, but move the clients into the app, and move the app itself into the returned object. That will be possible with the upcoming C++ version. But currently, either you make them pointers (using shared_ptr), or you keep copying them. Another option would be to use auto_ptr, which has a pseudo-transfer-of-ownership semantic. But that template has some inherent problems. So you should avoid using it.