1

I have recently been trying to remove the use of singletons and global variables from my project but I am having a hard time doing so. I have somewhat devised a better alternative to the singletons and global variables but I am not sure how to handle the data once my application is terminated.

My application needs access to a couple of things for most of the components to work properly; Some components need to access static std::vector<Foo*> foos;and others need to access static std::vector<Bob*> bobs; and some needs to access both. What I have done is created "Managers" for these vectors, a FooManager which gives access to the protected static vector to a class inheriting it and a BobManager which does the same thing for the other vector. By doing this limit the scope of these two objects. My problem is at process termination how and where do I deallocate the pointers in each vector? Multiple classes are now "Managers" of these objects. From the derived class? but what if I deallocate something while another class needs the original data?

Basically my question is how do I avoid deleting the pointers when I shouldn't be? unique_ptr? shared_ptr? Also any other implementation of this is welcome.

arnm
  • 1,705
  • 2
  • 19
  • 30

2 Answers2

1

If you have the choice in your design, Idan's last paragraph is the way to go (included again):

If you still insist on avoiding the Singleton pattern, what I would recommend is to make those vectors non-static again, create a single instance of each manager once at your main function or any other root-ish function, and pass them to any other object that needs them. Yes, that's alot of work - but it lets you control when those vectors(and the objects they point to) are created and destroyed. Or - you could just use singletons.

Your Question:

Basically my question is how do I avoid deleting the pointers when I shouldn't be? unique_ptr? shared_ptr? Also any other implementation of this is welcome.

Reference Counting is one way to solve your problem. It keeps track of the number of things that are interested in a set of data. A quick way (with your current implementation) is to include a variable in the manager classes that keep track of how many instances there are. In the destructor decrement the counter. If the counter is 0 delete your vectors.

David D
  • 1,571
  • 11
  • 12
0

If I understood correctly, you have those two vectors that need to be accessed globally, and you used to have singletons to handle each. Now you want to remove those singletons, and instead make those vectors static members and have many instances of of the Manager classes?

Don't. Just... don't.

Global variables are a problem. There is a misconception that singletons are a kind of global variables and therefore are also a problem. They are not - singletons are the solution to the global variables problem. Removing the solution does not mean removing the problem - it just means you have a problem without a solution.

If you still insist on avoiding the Singleton pattern, what I would recommend is to make those vectors non-static again, create a single instance of each manager once at your main function or any other root-ish function, and pass them to any other object that needs them. Yes, that's alot of work - but it lets you control when those vectors(and the objects they point to) are created and destroyed. Or - you could just use singletons.

Idan Arye
  • 12,402
  • 5
  • 49
  • 68
  • 3
    Please substantiate in what way singletons solve the problem. – Luc Danton Feb 07 '13 at 01:54
  • What is the problem? Why do people say singletons don't solve the problem? Why are they wrong? – Drew Dormann Feb 07 '13 at 01:59
  • The asker is worried about releasing the pointers of the vectors at the end of the process. I assume that the memory is not the problem - since the process is finished and the memory is freed anyways - but calling the destructors of the objects referred by those pointers. Some implementations of the Singleton pattern in C++ allow a destructor that will be called at the end of the program - so you can use that destructor to do the cleanup. – Idan Arye Feb 07 '13 at 02:15
  • 1
    Sorry, I was quoting from your paragraph -- the whole of it is what I want to see substantiated. From your own words: in what way are singletons the solution to the global variables problem? – Luc Danton Feb 07 '13 at 02:19
  • 2
    It makes it easier to debug your application when you know what has access to what by a compile time contract. By having singletons and global variables you don't know if one of them was modified some where it shouldn't have been and it also destroys otherwise correct functions by referencing them inside of it (you don't really know what your functions really do if you have globals/singletons flying around). That's why I don't want to use them. – arnm Feb 07 '13 at 02:21
  • The problem with global variables is that the same data can be accessed from anywhere - which makes it hard to follow the state of the data or to access it concurrently. A singleton solves this in the OOP way - only the singleton object's method can access that data. This gives you a single place to look at when you want to debug - you can put a `cout` command at the singleton's methods to track the changes in the variables, put `assert`s to force a contract on the data, put a breakpoint in your debugger etc. – Idan Arye Feb 07 '13 at 02:43
  • 4
    @IdanArye A global object is free to have the same exact methods as a singleton object. – Luc Danton Feb 07 '13 at 02:45
  • @LucDanton True, but you can't control their construction. A singleton is only constructed the first time you call it's `getInstance` method, while a global object is constructed somewhere before `main` is invoked. That also means that any Exceptions thrown from a global object's constructor will not be caught but whatever error-logging mechanism you put in `main`. Also, that means that you need to either make the constructor global(which would mean other instances can be created) or make the global object a static member of the class. But, if those are not problems - I see not reason not to. – Idan Arye Feb 07 '13 at 03:02
  • 1
    Luc is correct singleton pretty much is an OO global. Its just a lazy way to fix the problem additionly to the obvious design problems that Luc said. Think about singletons and multithreading, its just a no no. – Chris Condy Feb 07 '13 at 03:07
  • 1
    @ChrisCondy singletons are actually worse than OO globals as they enforce that only _1_ instance of the type be allocated at any time, while a global manager could live along side another global or local other instance of the same type of manager – emartel Feb 07 '13 at 03:20
  • @ChrisCondy Concurrency is another problem that singleton solves. If all those threads do need to access the same data, you can just implement the appropriate concurrency technique in the mutators of the singleton. If you actually want a different set of global data for each thread, it's pretty easy to alter the singleton pattern so that the `getInstance` method will return a thread-local instance, that will be destroyed when the thread is destroyed. – Idan Arye Feb 07 '13 at 03:21
  • @emartel That's like saying that `const` is bad because it prevents you from altering the variable's data. The whole point of the singleton pattern is to handle cases where there can only be one instance. – Idan Arye Feb 07 '13 at 03:23
  • 1
    @IdanArye don't get me wrong, I do use Singletons, where they fit, but some people tend to use them at too many places without differenciating "should generally be only 1 instance" and "_must_ be only 1 instance" – emartel Feb 07 '13 at 03:27
  • Most techniques are bad when used incorrectly. Most of the arguments against singletons are actually arguments against global state - my point is that if you do need global state, you should use singleton to handle it. Singleton does not introduce any new problems to global state - on the contrary: is solves some of the global state problems. Anyways, the asker didn't want to use singletons but he still used global state. Instead of one object accessible from anywhere he created multiple objects that access the same data. I don't see how this solves any of the problems associated to singleton. – Idan Arye Feb 07 '13 at 03:57