Thread: Global Varibles

  1. #16
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    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?
    No it's not easy. We can't see the rest of your code, so we can't do it here either.
    It's all connected to your ability to design, refactor, make abstractions, encapsulate, isolate functionality and that sort of thing. There is no doubt a near-perfect way to write the program you're trying to write, and it will not have these as globals at all, but it is simply not something that you can learn directly or learn on its own. Instead it falls naturally from learning the things I just mentioned. Until you get there, you just have to make the best of a bad situation, e.g. good naming etc, and keep learning how to program.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  2. #17
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by motocross1 View Post
    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")?
    Nobody is speaking against parameters to functions, that's actually what I am arguing for. Coupling is reduced when necessary data items are passed into a function, it is increased when the function reaches outside itself to get them. Neither of these is inherently bad, it is a matter of balancing the two so that the actual control flow is made clear, while reducing the potential for mysterious/unexpected state changes.

    Imagine the complete program state as a graph, with actual data items as nodes and accessibility relationships as links between them. Now consider a "window" or subgraph on that graph, which is the set of items that some function actively works with. The number of edges leading outside of that subgraph is a measure of how encapsulated that subset of state really is. In object orientation, you recognize commonly occurring subgraphs in the program state and wrap those up inside objects, give them interfaces, and call them "classes."

    A global variable is like a node in this graph that has an edge to every other node. It inherently breaks encapsulation and defies attempts to identify useful class abstractions.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  3. #18
    Registered User rogster001's Avatar
    Join Date
    Aug 2006
    Location
    Liverpool UK
    Posts
    1,472
    Imagine the complete program state as a graph, with actual data items as nodes and accessibility relationships as links between them. Now consider a "window" or subgraph on that graph, which is the set of items that some function actively works with. The number of edges leading outside of that subgraph is a measure of how encapsulated that subset of state really is. In object orientation, you recognize commonly occurring subgraphs in the program state and wrap those up inside objects, give them interfaces, and call them "classes."

    A global variable is like a node in this graph that has an edge to every other node. It inherently breaks encapsulation and defies attempts to identify useful class abstractions.
    I like this and the 'Lake ' post from MK27, lovely analogies and I hope you benefit from this insight to the arguments posted
    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. #19
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by motocross1 View Post
    Yes, I know C++ is synonymous with "everything must be a class".
    It doesn't have to be, but most of it probably should or you are not taking full advantage of the language.

    The "mess" project I was referring to was actually written in C, but it is not a mess because C does not have classes, and so I "had to" use globals. It could have been done without globals in C, by using modular components (which is sort of pseudo OOP).

    But C++ will also always need functions that take parameters.
    Sure, that's what a method is.

    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 am, absolutely. This way you can pass stuff around (see brewbuck's point in post #17). This doesn't mean you have to end up with ridiculously long parameter lists; classes and structs can contain multiple fields; so a single struct or object parameter can provide access to a variety of data. That's organization.

    I honestly want my function parameters to be specific to the function.
    Besides, if I start passing everything, then some functions will be stuffed.
    You don't need to avoid long param lists, just unnecessarily long ones, which you avoid by thinking about organization. I often find that at a certain point, it is my parameter lists that provide a clue about the possibility of creating a new class or struct. Eg, if you find yourself passing the same three variables around everywhere, this is a clue that maybe they belong together.

    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?
    No, the functions will pass a user object in order to avoid the global. Of course, if the functions are actually methods of the user class, then they don't have to do that, or explicitly pass parameters internal to the class, because they're there inside it (as opposed to globals, which are there outside it).

    Remember, you can create one way relationships between classes. For example, with a GUI like a web browser, you might have a class representing a browser window, a class representing a single tab, and a class representing a page. The window class would contain an array of tab objects, and the tab class would contain a single pointer to a page object. These are "one way" relationships because the page class does not need to contain a reference to a tab, and the tab class does not need contain a reference to the window (at some point, of course, you might realize this should be a two way relationship).

    Not exploiting classes is like not exploiting functions (ie, just doing everything, repetitively, in main). It does take practice, but if you never start, you'll never get out of the box you are in.

    Please, let me know (maybe with examples too).
    Thanks
    Here's an idea: post your current code, or some simplified model of it, and I guarantee you'll get a bunch of ideas about how to re-arrange it in keeping with the theme of this thread. Way more so than if you wait for contrived examples.
    Last edited by MK27; 03-03-2012 at 03:04 PM.
    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

  5. #20
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Actually, my criticism of global state is based somewhat differently.
    ^_^

    It clearly isn't. I'd imagine that if someone asked us to create a list of everything wrong with global variables we would both hit on almost the same points. You only have a less rigid definition for global state than I do.

    I consider constant tables, such as those used to implement a state machine for example, as being global state; it is only immutable.

    I consider this:

    Code:
    #define Initialize 0
    #define Finalize 1
    #define Advance 2
    #define Compare 3
    or even this:

    Code:
    enum TStates
    {
        Initialize
      , Finalize
      , Advance
      , Compare
    };
    as being global state when more than one single function in a mutually recursive state machine ever uses it. (You have implied that it is global state even when a single function uses it, but I rather doubt that's what you mean.)

    I consider passing a "90%" bit of global state around by parameter as global state. Such an "anti-pattern" is still subject to the same criticisms as most any other global state. You are only saying, for whatever reason, that such would not be global state because the function isn't "reaching outside itself". The problem is, by passing the actual global state around you are allowing that function to "reach outside itself" by proxy. You are only trying to disguise it. Hiding that state behind a pointer passed everywhere doesn't change anything. Any function in the chain (not just a function calling another function but even "siblings") can corrupt that global state in a variety of ways and everything "up stream", "down stream", and "sideways" might break because of it exactly as if it had been a simple global variable.

    *shrug*

    Look for a moment at your graph example. It doesn't really explain why the "Singleton" pattern is bad to a newbie because it would look to a newbie like the data the singleton represents is only accessible by the singleton apparently reducing coupling on global state because fewer links exist between desperate components. (We know it doesn't really do that.) Still looking at that graph example, consider the "pass a pointer everywhere" approach. That's absolutely not the same thing as associating relevant data and putting them into a class. Sure, it looks like the dependencies have a nice hierarchy of responsibilities but by simply passing global state around you've said "links can flow anywhere and everywhere".

    Consider function `A' that calls `B' and `C'. Functions `B' and `C' know nothing about each other. Functions `B' and `C' need access to global state. (It doesn't matter what.) Instead of a redesign and rewrite you only wrap the global state with a pointer and pass that into `B' and `C'. `B' and `C' have a real dependency even though it doesn't look like it because `B' or `C' may break that global state causing problems for everyone else.

    Now, you can solve that issue, but it means doing the work of designing and using components properly. For example, you might break out the global state that `B' and `C' needs and make that state a class for the interface by having real parameters of the appropriate class type. (Simply explicitly copying that global state and passing copies around solves part of those particular problems.) However, it is clearly more work and exactly why most people will not do it and wind up with global state. I don't mean just in rewrites either; programmers, especially newbies, developing new code will just as often use some form of global state so that they don't have to deal with figuring out and using an appropriate interface.

    Soma

  6. #21
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by phantomotap View Post
    I consider passing a "90%" bit of global state around by parameter as global state. Such an "anti-pattern" is still subject to the same criticisms as most any other global state. You are only saying, for whatever reason, that such would not be global state because the function isn't "reaching outside itself". The problem is, by passing the actual global state around you are allowing that function to "reach outside itself" by proxy. You are only trying to disguise it. Hiding that state behind a pointer passed everywhere doesn't change anything. Any function in the chain (not just a function calling another function but even "siblings") can corrupt that global state in a variety of ways and everything "up stream", "down stream", and "sideways" might break because of it exactly as if it had been a simple global variable.
    I'm not being clear, I guess. I don't condone passing around pointers to big bags of state. What is passed into a function should be the minimal set of data items necessary for it to achieve its functionality. For instance, suppose you had a class that determined whether a person's first name is a male name or a female name (obviously in some cases the function could get it wrong, but it's beside the point). Furthermore, suppose that people are represented by Person objects which have a GetFirstName() method.

    You might implement GetNameGender() a couple of ways:

    Code:
    Gender GetNameGender(const Person &person);
    GetNameGender(brewbuck); // call it
    // or...
    Gender GetNameGender(const std::string &name);
    GetNameGender(brewbuck.GetFirstName());
    I argue for the second option, because it passes only the required information into the function. It shrinks the window of program state which is available to the function and prevents it from expanding to other purposes.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  7. #22
    Registered User
    Join Date
    Feb 2010
    Posts
    98
    So, I've posted the fact that I use global bool's, int's, string's, double's.
    But I did not mention I also use several global struct's.
    In my Global.h:
    Code:
    struct myStructData{ string name; int num; bool isReady; };
    extern vector<myStructData> StructData;
    Then again, at the top of my Main.cpp:
    vector<myStructData> StructData;

    I also did not mention that my globals are used inside several threads (CreateThread), which have their own struct pointer passed into the lpParameter.

    This makes me wonder now...
    Different windows, functions, and threads use StructData.
    So isn't StructData global in use?

    Wouldn't any class I package my global variables into still be nothing more than a global struct?
    Global Variable vs. Global Anything - Is there really a difference?

  8. #23
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Packaging of global variables doesn't make them non-global. It only changes how they are organised, but they are still global.

    The point of other posts in this thread is that there are techniques to avoid using global variables altogether. Generally, that means functions need to accept arguments (and optionally returned values), and data gets passed via function call mechanisms. All objects, data structures, and variables have a defined lifetime - that is true even with dynamic memory allocation, if the programmer remembers to manage the dynamic memory.. If a function Foo() creates an object (e.g. defines it locally) that object can be safely passed by reference, or copied by value, to all functions that Foo() calls, as it is guaranteed to exist. As far as the called functions are called, there is virtually no difference between an object passed as an argument and a global: both are guaranteed to exist, unless other code has misbehaved.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  9. #24
    Registered User
    Join Date
    Feb 2010
    Posts
    98
    Passing data into functions is easy for me to grasp (adding another argument is easy too).
    It's all of the threads and popup/child windows that leave me wondering how do globals (or handle my data) more professionally.
    And by the way, in any function or thread or window procedure that I can do static variables I do them.
    Simply put, I view global data as RAM and application-config-files as ROM.
    I just want to load my app data into memory and use it everywhere no-strings-attached.

    there is virtually no difference between an object passed as an argument and a global
    Sounds good to me - I'll just leave it at that.
    Thanks everyone.

  10. #25
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    I just want to load my app data into memory and use it everywhere no-strings-attached.
    O_o

    Can't be done; every decision you make as a programmer has "trade-offs"; if you don't want to deal with it, you may as well just use global variables directly.

    [Edit]
    It's all of the threads and popup/child windows that leave me wondering how do globals (or handle my data) more professionally.
    And we can't answer that question with the information we have. iMalc, brewbuck, and MK27 weren't joking or exaggerating. Different situations call for different solutions and we have no idea what your situation may call for.
    [/Edit]

    Sounds good to me - I'll just leave it at that.
    Swing and a miss!

    Soma
    Last edited by phantomotap; 03-03-2012 at 06:14 PM.

  11. #26
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by motocross1 View Post
    Passing Sounds good to me - I'll just leave it at that.
    You've taken Grumpy's statement out of context. He said "As far as the called functions are called, there is virtually no difference between an object passed as an argument and a global: both are guaranteed to exist, unless other code has misbehaved."

    The statement by itself, as you reposted it is very much false.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  12. #27
    Registered User
    Join Date
    Feb 2010
    Posts
    98
    Okay?
    What's the difference then between global data and data passed into a function?
    Why is one better?

  13. #28
    Registered User
    Join Date
    Feb 2010
    Posts
    98
    Also (FYI)... my code is very similar to:
    WIN32API code: Listview control
    Just more windows and feature (as in 10000 lines of code).

  14. #29
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by motocross1 View Post
    Okay?
    What's the difference then between global data and data passed into a function?
    Why is one better?
    You might want to read through other posts in this thread, for starters. As iMalc said, you have misinterpreted my previous post. I was certainly not providing an argument that you can or should use globals, although you have selectively misinterpreted my words that way.

    A fundamental principle of system engineering is that big problems are more easily understood by breaking them down into smaller, self-contained, problems.

    In programming, that means that functions need to be designed so they perform in a well-defined manner on a well-defined set of inputs, and produce a well-defined set of outputs. That is often defined in terms of locality: the inputs come via one path, the outputs leave via one path, in a manner that can be described in simple terms (or in terms that are no more complex than necessary).

    The main argument against global variables is precisely because they enable, by definition, non-locality. Any function that uses a global variable can obtain data via some path unknown to, or even invisible to, its caller. Its behaviour (input it looks at, output it produces, time it takes, memory it consumes) therefore depends on ANY other code that happens to manipulate the global data. The same goes for any function that, directly or indirectly, calls your function. The result is mutual dependencies between all functions that access the global data. That makes it much harder to get all of the functions working correctly, in tandem. It also means that, if you introduce some new function that manipulates the global data, that you can accidentally break any of your other functions which USE that global data.

    The larger a program, the more complex it tends to be. In VERY small programs, globals can sometimes appear to make things simpler. The problem is that, in larger programs, globals usually affect the architecture (basic conceptual organisation) of the program, and make it harder to get things right.
    Last edited by grumpy; 03-03-2012 at 10:38 PM.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  15. #30
    Registered User
    Join Date
    Dec 2010
    Posts
    15
    The result is mutual dependencies between all functions that access the global data. It also means that, if you introduce some new function that manipulates the global data, that you can accidentally break any of your other functions which USE that global data.
    That is true, so every global data should be a class with functions to access its contents. The functions allow to control simultaneous access from different threads and can check data for validity before changing a global state.

    Almost any complex program has global data. It is too hard to pass pointers between functions all the time.

    Packaging of global variables doesn't make them non-global. It only changes how they are organised, but they are still global.
    They may be less global. Imagine the program itself is a class. As any other class it has members that you can access. The Program is singleton, there is only one instance and you can't create more. That instance lives while application executes.

    Code:
    #include <stdio.h>
    
    class CSettings
    {
    };
    
    class CProgram
    {
    private:
    	CSettings m_settings;
    	static CProgram m_instance;
    	CProgram()
    	{
    		// Write your program here
    		printf("Hello, world!");
    	}
    public:
    	static CProgram* GetInstance() {return &m_instance;}
    	CSettings& settings() {return m_settings;}
    };
    
    CProgram CProgram::m_instance;
    
    int main()
    {
    	return 0;
    }

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