Thread: Global Varibles

  1. #1
    Registered User
    Join Date
    Feb 2010
    Posts
    98

    Global Varibles

    I currently do my globals by creating them in Global.h ( extern int myInt; ) and then initializing them near the top in various cpp files ( int myInt=123; ).
    But, what is the "professional" way?
    (other than not use globals, which I find hard to believe is possible)
    Thanks
    Last edited by motocross1; 03-02-2012 at 03:21 PM. Reason: undo wink icon

  2. #2
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    Global variables aren't the same as global state.

    Global variables increase coupling, may pollute the global scope, can have weird construction order problems, and you have very limited control over how the data those variables represent is used.

    Global state is simply some data that can be access from anywhere in code; it may not have any of those problems.

    There are issues with global state, but that applies to any form global state including actual global variables, singletons, and other techniques. (The singleton pattern alone doesn't solve this problem; it would need to be combined with other techniques.)

    You can absolutely avoid global variables.

    You can't really avoid global state, but by wrapping it with some technique or another you can solve the problems of actual global variables.

    And this being C++ we are talking about, you can also get the best features of global state without forcing global state on client code in the form of overloaded or default parameter values referencing global state.

    [Edit]
    Code:
    void DoSomething
    (
        int fSomeData
      , int * fOtherData = GetGlobalData()
    );
    [/Edit]

    Soma
    Last edited by phantomotap; 03-02-2012 at 04:36 PM.

  3. #3
    Registered User rogster001's Avatar
    Join Date
    Aug 2006
    Location
    Liverpool UK
    Posts
    1,472
    (other than not use globals, which I find hard to believe is possible)
    I may invite critiscism here for naivety but I beleive global variables to be nothing more than weak and or lazy programming design, when the language is so rich in its options. I use some globals more in VBA only because i have been too lazy so far to find out properly about scope, and because in the face of C++, well , VBA is a bit baby language so am probably being a code snob haha, it will smack me in the face soon am sure!

    They tend to become nothing more than a pain in the arse to keeep track of and a liability, and you always ask ' there must have been a way around that'

    Saying that I can only see it from the level i code at, perhaps globals are a very useful, oft used tool in the right hands, library writers or whatever.

    But there is no way I would have a globals.h file full of integer declarations and assignments
    Last edited by rogster001; 03-02-2012 at 06:27 PM.
    Thought for the day:
    "Are you sure your sanity chip is fully screwed in sir?" (Kryten)
    FLTK: "The most fun you can have with your clothes on."

    Stroustrup:
    "If I had thought of it and had some marketing sense every computer and just about any gadget would have had a little 'C++ Inside' sticker on it'"

  4. #4
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by rogster001 View Post
    I may invite critiscism here for naivety but I beleive global variables to be nothing more than weak and or lazy programming design
    I don't think anybody will disagree with you here. Although I'd describe global variables as a total LACK of design, not just a poor one. They are substitute for an actual design.

    It's not just global scope that's bad, but global state itself (whether the global state is achieved by a singleton or whatever). Global state by definition can be accessed and modified by any piece of code, anywhere. It's like you and six of your friends sharing the same locker in high school. Not only will it get crammed with a bunch of junk you don't care about, it opens the possibility to make a serious mistake, such as going home with the wrong backpack.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  5. #5
    Registered User rogster001's Avatar
    Join Date
    Aug 2006
    Location
    Liverpool UK
    Posts
    1,472
    Well I am pleased about that affirmation, and the point about state also, the amount of head scratching that this stuff can invoke, you just dont need it!
    Thought for the day:
    "Are you sure your sanity chip is fully screwed in sir?" (Kryten)
    FLTK: "The most fun you can have with your clothes on."

    Stroustrup:
    "If I had thought of it and had some marketing sense every computer and just about any gadget would have had a little 'C++ Inside' sticker on it'"

  6. #6
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by brewbuck View Post
    It's not just global scope that's bad, but global state itself (whether the global state is achieved by a singleton or whatever).
    Is making them static and putting into an implementation file, leaving the only way to access them by functions with suitable locks, a good solution when the program needs something to be globally available ?

    (I'm not sure if that's what phantomotap was saying in #2)

  7. #7
    Registered User rogster001's Avatar
    Join Date
    Aug 2006
    Location
    Liverpool UK
    Posts
    1,472
    Is making them static and putting into an implementation file, leaving the only way to access them by functions with suitable locks, a good solution when the program needs something to be globally available ?
    If the program needs something to be globally availablle then surely that can be supported through the overall design, eg led by the top level class?
    Last edited by rogster001; 03-02-2012 at 07:28 PM.
    Thought for the day:
    "Are you sure your sanity chip is fully screwed in sir?" (Kryten)
    FLTK: "The most fun you can have with your clothes on."

    Stroustrup:
    "If I had thought of it and had some marketing sense every computer and just about any gadget would have had a little 'C++ Inside' sticker on it'"

  8. #8
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by rogster001 View Post
    If the program needs something to be globally availablle then surely that can be supported through the overall design, eg led by the top level class?
    Like this ? God object - Wikipedia, the free encyclopedia
    (From the tone of the article, it doesn't seem to be well recommended.)

  9. #9
    Registered User rogster001's Avatar
    Join Date
    Aug 2006
    Location
    Liverpool UK
    Posts
    1,472
    yes but that depends on the size of the project: this 'god object' is in fact when taken too far little different from the global variable, i see that. But again I think would be a design oversight, to rely too heavily on the one in that manner, of course we are talking perfect worlds here, but at least the coder is control of it,(so far as they can keep track!) and is not passing interpretation elsewhere.

    Generally i am interested in this, I beleive the language provides for a well constructed program without any recourse to global variables in the traditional sense, if anyone can provide solid evidence for a general case to the contrary, I would like to see it.
    Last edited by rogster001; 03-02-2012 at 07:58 PM.
    Thought for the day:
    "Are you sure your sanity chip is fully screwed in sir?" (Kryten)
    FLTK: "The most fun you can have with your clothes on."

    Stroustrup:
    "If I had thought of it and had some marketing sense every computer and just about any gadget would have had a little 'C++ Inside' sticker on it'"

  10. #10
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    [Edit]I don't know why this didn't come up before, but the criticisms of global state apply to mutable state. Global tables and constants may have issues of their own, but the same criticisms rarely apply.[/Edit]

    Is making them static and putting into an implementation file, leaving the only way to access them by functions with suitable locks, a good solution when the program needs something to be globally available ?
    The state itself would still be global so any criticism that applies to global state would still apply. The "restricted" access only hides what is essentially a global variable. A lock (I'm assuming you mean something like a binary semaphore.) only prevents race conditions (for example). That said, these are fine goals.

    Let me give an example.

    Actually, no, let me reference another thread posted here recently. The code posted was terribly broken because global variables had been used. If you were to hide that global state with functions, singletons, or "TLS" the code would still have been broken because one function using those variables was intended to be recursive.

    Hiding state behind strict controls is always good. Prevent code from breaking in the face of threads is always good. These techniques just don't solve all the issues with global state. Actually, they can make it worse if not carefully documented.

    If the program needs something to be globally availablle then surely that can be supported through the overall design, eg led by the top level class?
    A "top level" class is only another way of hiding global state. Putting state behind `this' that every "top level" method may use is no different than having a global pointer and passing it to free functions. It solves some of the problems, but not all of them. Specifically, it solves some of the issues of reusing that component in other applications.

    Like this ?
    A "god object" and a "top level" class are not the same thing.

    A "god object" is broken promise for "OOP" programmers so that they don't have to fall back on "teh evils" procedural programming model. With a "god object" you literally just cram every necessary member (data) and method (functions) into a single class. It is almost the same thing as having one incredibly complex function versus gluing multiple smaller (decomposed) functions together.

    A "top level" class is simply the program driver built into a class. Trivially, you put `main' in a function of a class and create an instance of that class in `main'. It can be more complex than that, but basically the "top level" class does the dirty work of gluing components (free functions and classes) together instead of doing it with `main'. This could be compared to function composition.

    Generally i am interested in this, I beleive the language provides for a well constructed program without any recourse to global variables in the traditional sense, if anyone can provide solid evidence for a general case to the contrary, I would like to see it.
    Well, again, global state and global variables are different.

    You can absolutely build an application (of any complexity) without global variables, but global state is another issue.

    Consider an extreme practice: you add an extra pointer parameter to every function and pass a "struct NotAtAllGlobalData" every invocation. That alone doesn't change much of anything; it may not look like global state, but it is a candidate for almost every criticism of global state.

    That's the biggest problem with global state; you can decorate it all you like, but you can't solve all the problems unless you literally never use it.

    You want to get rid of all global state? You'll probably need to switch to a design having interfaces with only immutable state while avoiding anything complex. Don't get me wrong; that isn't actually a necessity, but it will prevent you from relying on global state by accident.

    Consider the "Windows" GDI model, you have to have global state because the system doesn't guarantee that you own some resources. (You create a handle to those resources which can be obtained in many different ways at any point in the program.) Okay, you solve that problem by documentation and applying good design principles at the application level. (You say "Object `SmartHandle' owns this resource so all access to that resource must be through `SmartHandle'." even if it isn't really true.)

    *shrug*

    You want a good rule of thumb: "Avoid global state that only provides convenience.". I know it sounds retarded, but it is about the best you can do and still get anything done.

    Soma

  11. #11
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    I'm afraid I don't understand your explanation of "top level class" very well.
    Consider this little main.cpp . Is mm::repl the sort of class you've mentioned ?

    Also, in the topic of global tables, I can't see a way to avoid them.
    Suppose a table stores key-value pairs which, as resources, are relevant to others in the program.
    What can be done other than putting up a huge global object as public property?

  12. #12
    Registered User
    Join Date
    Feb 2010
    Posts
    98
    Hello again, thanks for all of the replies.
    I knew ahead of time this would cause debate.
    I knew the phrase "lazy programming" would be thrown out too.
    Oh well, it is what it is.

    Quote Originally Posted by rogster001
    I beleive the language provides for a well constructed program without any recourse to global variables in the traditional sense, if anyone can provide solid evidence for a general case to the contrary, I would like to see it.
    Well here's an easy one:
    Code:
    bool isLoggedIn=true;
    string Username="motocross1";
    int AccountRestictions=11;// bitwise
    All of these are changed in only one function, but are used in dozens of other functions.

    Now then, please put the debate aside for a moment though.
    What is the "professional" way to make them global?
    As I've posted originally, I do extern in the Global.h, declare at the top in Main.cpp.
    Thanks again.

  13. #13
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by phantomotap View Post
    [Edit]I don't know why this didn't come up before, but the criticisms of global state apply to mutable state. Global tables and constants may have issues of their own, but the same criticisms rarely apply.[/Edit]
    Actually, my criticism of global state is based somewhat differently. It is not the accessibility of the state but the manner in which it is accessed. State should flow explicitly between components, not reside in a repository with a huge pipe leading to it. There should be itty bitty pipes leading between the components which need to operate on that state. A particular piece of state may be accessed by 90% of the objects which exist, and that's fine, but they should access it through pathways that are easily traceable and there should be a clear chain of responsibility for that state which is visible in the code. Reaching into a big bag of state and grabbing something, leads to confusion.

    Quote Originally Posted by motocross1
    Now then, please put the debate aside for a moment though.
    What is the "professional" way to make them global?
    As I've posted originally, I do extern in the Global.h, declare at the top in Main.cpp.
    Thanks again.
    If you insist on having them, at least give them names that make it clear they are global (prefix them with g_ or Global or something like that) so you can easily search for them and measure just how much the code sucks. Declare them all in one header as extern (so this header can become a target for extermination) and define them all in a single file like Globals.cpp. All of this stuff should be on your hit list to eliminate over time.
    Last edited by brewbuck; 03-03-2012 at 10:57 AM.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  14. #14
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by motocross1 View Post
    Well here's an easy one:
    Code:
    bool isLoggedIn=true;
    string Username="motocross1";
    int AccountRestictions=11;// bitwise
    All of these are changed in only one function, but are used in dozens of other functions.

    Now then, please put the debate aside for a moment though.
    What is the "professional" way to make them global?
    Don't I see a "user" class here? Even if currently your program is intended to deal with only one user at a time, you might as well make that a class. Some of your global functions could become methods of the class, and the others tweaked to handle a user object as a parameter (and, perhaps, themselves incorporated into a class). Then when the program begins, you instantiate a user object (and whatever other objects are appropriate) local to main() and go from there. So you might, initially, have two singular objects, eg, a "user" and a "process", which do all the work. But they are not global -- they are passed back and forth following the logic of the classes which define them. In addition to being a more flexible and extensible design, this accomplishes the point here:

    Quote Originally Posted by brewbuck
    State should flow explicitly between components, not reside in a repository with a huge pipe leading to it. There should be itty bitty pipes leading between the components which need to operate on that state. A particular piece of state may be accessed by 90% of the objects which exist, and that's fine, but they should access it through pathways that are easily traceable and there should be a clear chain of responsibility for that state which is visible in the code.
    The value of this becomes clearer as the code base grows. When you get up into the thousands of lines, it is much easier to deal with in terms of "itty bitty" streams than in relation to a lake. If you change something in a lake, everything in the lake may be affected. If you change something in a stream, ideally, this cannot affect things in other streams. It is easy to deduce what will happen to something when you drop it into a stream. You can make deductions in a lake, but you stand a much higher chance of getting blindsided in your understanding.

    The Magical Number Seven, Plus or Minus Two - Wikipedia, the free encyclopedia

    I have an absolute mess of a project I wrote 4-5 years ago that made excessive use of globals -- I thought this was fine because it was a GUI, and there could only be one instance of the interface (so why not make it globally accessible?). I still use and (marginally) maintain it. It's a textbook nightmare, honestly. Every time I go to fix or change something, I have to follow a breadcrumb trail on a 200kb (very sparsely commented) lake bed; over time I've reigned it in a bit, but my gut feeling right now is that the easiest way to get it into decent shape would be to literally re-write the whole thing from scratch.

    So take it from someone who learned the hard way. Make it a priority to avoid any kind of global state what-so-ever. It is easy once you get the hang of it and it you'll hate yourself less in the long run.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  15. #15
    Registered User
    Join Date
    Feb 2010
    Posts
    98
    Yes, I know C++ is synonymous with "everything must be a class".
    But C++ will also always need functions that take parameters.
    So I need to ask those of you recommending I use a class...
    Are you recommending that my functions should include another parameter (i.e. a pointer to my "user class")?

    I honestly want my function parameters to be specific to the function.
    Besides, if I start passing everything, then some functions will be stuffed.
    Plus, windows messaging with several child windows, blah, blah.
    Hence the use of globals.

    Am I missing the meaning of how the class would be used?
    If the functions will NOT pass the "user class" pointer, then what makes it anything different than a global use?
    gUser->isLoggedIn is the same a global_isLoggedIn right?
    (yes, only 1 user per app)

    Please, let me know (maybe with examples too).
    Thanks

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. string varibles??
    By Labmouse in forum C++ Programming
    Replies: 2
    Last Post: 08-23-2007, 08:16 AM
  2. Declaring Varibles
    By lbrault in forum C++ Programming
    Replies: 6
    Last Post: 02-05-2003, 12:23 PM
  3. extern varibles
    By manwhoonlyeats in forum C Programming
    Replies: 5
    Last Post: 12-18-2002, 12:43 AM
  4. C Functions and varibles
    By mart_man00 in forum C Programming
    Replies: 13
    Last Post: 08-01-2002, 01:11 PM
  5. varibles
    By Klinerr1 in forum C++ Programming
    Replies: 8
    Last Post: 06-24-2002, 10:15 AM