Re: Static initialization order
On 19/09/2013 07:41, DeMarcus wrote:
Global variables are "evil" but global /objects/ are not. However, with
global objects come their constructors that must run before main() if
you don't make them pointers.
I am curious, what do you consider to be the difference between a
variable and an object? Why, globally, is the former bad whilst the
latter is not?
Perhaps explaining why global variables are bad (I would say, 'should be
avoided if possible) would be a start (yes I think I know the answer).
Global variables are as bad as public variables. Objects using them are
impossible to keep consistent with invariants. A global /object/ on the
other hand can still be kept consistent.
You are still missing the point. You seem to think that there is some
essential difference in C++ between a variable and an object. If you
want to define what you mean by an object that distinguishes it from a
variable we might then be able to have a more meaningful dialogue.
The issue with globals is not about maintaining their internal
consistency but about the consequences of having them accessible from
many places in a program. That makes testing much harder and more
complex. It also makes predicting outcomes much harder.
Here is a simple example to highlight one of the problems
class object {
// some suitable definition providing
// all the possible benefits from
// encapsulation
};
object obj{/* initialisation data */}
void foo(object const & o);
int main(){
object obj1{obj}; // create a copy of the global
foo(obj1);
foo(obj); // call foo with the global
std::cout << (obj == obj1 ? "X" : "Y") << std::endl; // A
}
What is the expected output? It is impossible to answer without knowing
the detail of foo()'s definition and the definitions of all functions
called by foo() (recursively) I.e. you need to know the full details of
the implementation of foo().
Here is a trivial definition of foo() that would generate 'Y' as output:
void foo(object const & o){ obj.modify();}
// with modify changing the state of an instance of type object
Once we have a global non-const 'object' we have no certainty as to its
state once we call a function and pass it a reference or pointer to that
object.
That is the fundamental problem with globals; we can only know how their
state evolves over the process of executing a program by knowing the
details of the whole program. Note that this problem can seriously
effect potential optimisations that we could benefit from by passing
arguments to const reference parameters. As soon as there is a global of
the relevant type the compiler has to deal with much more complex scenarios.
for example:
suppose that foo()'s implementation calls bar(object const & ob). Now
the compiler needs to be concerned about whether bar can change the
global. Within the implementation of foo() it has to consider the
possibility that it has been passed a reference to the global.
In real programs these problems can be easily masked. Programmers expect
that passing an argument to a const reference will not result in any
change to that object's state (and good programmers do not delete
objects that have been passed to them :) ), The existence of global
objects invalidates that expectation.
This problem is greatly magnified once we introduce multiple threads.
Francis
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]