There are plenty of reasons why globals are evil in OOP.
If the number or size of the objects needing sharing is too large to be efficiently passed around in function parameters, usually everyone recommends Dependency Injection instead of a global object.
However, in the case where almost everyone needs to know about a certain data structure, why is Dependency Injection any better than a global object?
Example (a simplified one, to show the point generally, without delving too deep in a specific application)
There is a number of virtual vehicles which have a huge number of properties and states, from type, name, color, to speed, position, etc. A number of users can remote control them, and a huge number of events (both user-initiated and automatic) can change a lot of their states or properties.
The naive solution would be to just make a global container of them, like
which can be accessed from anywhere.
The more OOP-friendly solution would be to have the container be member of the class which handles the main event loop, and be instantiated in its constructor. Every class which needs it, and is member of the main thread, will be given access to the container via a pointer in their constructor. For example, if an external message comes in via a network connection, a class (one for each connection) handling the parsing will take over, and the parser will have access to the container via a pointer or reference. Now if the parsed message results in either a change in an element of the container, or requires some data out of it to perform an action, it can be handled without the need of tossing around thousands of variables through signals and slots (or worse, storing them in the parser to be later retrieved by the one who called the parser). Of course, all classes which receive access to the container via dependency injection, are part of the same thread. Different threads will not directly access it, but do their job and then send signals to the main thread, and the slots in the main thread will update the container.
However, if the majority of classes will get access to the container, what makes it really different from a global? If so many classes need the data in the container, isn't the "dependency injection way" just a disguised global?
One answer would be thread safety: even though I take care not to abuse the global container, maybe another developer in the future, under the pressure of a close deadline, will nevertheless use the global container in a different thread, without taking care of all the collision cases. However, even in the case of dependency injection, one could give a pointer to someone running in another thread, leading to the same problems.