C++ Questions

I'm going to put all my questions about C++ here in this thread from now on so i have a handy and easy place to access them for reference as i read through and study LearnCPP.com.

So my first question is about Chapter 6.10, the static keyword. I understand what it does, but the site says:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>

void incrementAndPrint()
{
    static int s_value{ 1 }; // static duration via static keyword.  This initializer is only executed once.
    ++s_value;
    std::cout << s_value << '\n';
} // s_value is not destroyed here, but becomes inaccessible because it goes out of scope

int main()
{
    incrementAndPrint();
    incrementAndPrint();
    incrementAndPrint();

    return 0;
}


In this program, because s_value has been declared as static, it is created at the program start.

Now, my question is, are static variables created the second a program begins, or are they created the second they are initialized and then continue to have static duration? For example, when the program steps into the function and sees the variable, it then creates it and now it has static duration?

My assumption is that its created when the program first "sees" it just like a normal non-static local variable but im unsure.
Last edited on
I can't quote standard, so can't tell the real answer, but ...

Make a custom type. Make it's constructor say something. Use that type, rather than int for s_value. You should get output when the variable is initialized ...
cppreference wrote:
static storage duration. The storage for the object is allocated when the program begins and deallocated when the program ends. Only one instance of the object exists. All objects declared at namespace scope (including global namespace) have this storage duration, plus those declared with static or extern. See Non-local variables and Static local variables for details on initialization of objects with this storage duration.
https://en.cppreference.com/w/cpp/language/storage_duration#Storage_duration

I think initializing an object is essentially a synonym for creating the object. The lifetime of an object begins when the initialization is complete.

Note that there are different types of "static variables". Variables outside functions (declared with or without the static keyword) are normally created when the program starts, before the main function begins. Static variables inside functions are different. They are instead created/initialized the first time the execution reaches the variable declaration.
Last edited on
Interesting and simple example for Static variable declaration. The same thing that the classical declaration, but out of scope at start. Is there any difference between these alternatives :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>

int s_value = 1; // out of scope at start

void incrementAndPrint()
{
    // static int s_value{ 1 }; // static duration via static keyword. This initializer is only executed once.
    ++s_value;
    std::cout << s_value << '\n';
}

int main()
{
    incrementAndPrint();
    incrementAndPrint();
    incrementAndPrint();

    return 0;
}
Last edited on
In the above, s_value has global scope - and hence can be used from anywhere within the program.

If static at L7 used instead, then its scope is restricted to that function. More than one function can have the same named static variable and each would be distinct to the function in which it was defined and not available to other functions.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>

// All non-local variables with static storage duration are initialized as part of program startup,
// before the execution of the main function begins (unless deferred)
// https://en.cppreference.com/w/cpp/language/initialization#Non-local_variables
// Deferred dynamic initialization:
// see https://en.cppreference.com/w/cpp/language/initialization#Deferred_dynamic_initialization
int g = ( ( std::cout << "initialising ::g\n" ), 100 ) ;

int dummy = 5 ;

void foo( int arg )
{
    std::cout << "foo(" << arg << ")\n" ;
    if( arg > 10 )
    {
        std::cout << "arg is greater than 10\n" ;
        // Variables declared at block scope with the specifier static are initialized the first time
        // control passes through their declaration (unless their initialization is zero- or constant-initialization
        // (unless their initialization is zero- or constant-initialization, which may be performed earlier)
        // https://en.cppreference.com/w/cpp/language/storage_duration#Static_local_variables
        [[maybe_unused]] static int s = ( ( std::cout << "initialising foo::s\n" ), 200 ) ;
    }
}

int main()
{
    // ::g may be already initialised here (initialised before the execution of the main function begins)

    foo(2) ; // foo::s is not initialised (control does not pass through its declaration)

    // ::g would definitely be initialised here (before the first odr-use of a static non-local)
    ++dummy ; // odr-use of a variable with static storage duration, defined in this translation unit

    foo(55) ; // foo::s is initialised when control passes through its declaration for the first time
}

http://coliru.stacked-crooked.com/a/2de36249d029be82
Thanks for the responses, that pretty much confirms what i was thinking, just wanted to make sure. I have another question about Chapter 6.12. It tells me all the stuff i already know about using namespace std; which i dont do, I use using std::cout; etc in global scope, however none of the examples have this form in there, the using std::cout is there but they put it in main, is it bad to put it in global scope? I always thought that if i didnt use using namespace std; then it was fine.

1
2
3
4
5
6
7
8
9
10
#include <iostream>

using std::cout; //Bad?
using std::cin;  //Bad?

int main()
{
    cout << "Hello World!" << '\n';
    return 0;
}
It's a bit subjective or a matter of personal preference. The main guideline is to not put 'using' statements in header files, because in doing so you are forcing the user who #includes your header file to inject symbols into the global namespace, against the user's will.

Putting cout and cin into the global namespace of a local file is not likely to cause problems or make things hard to understand.
Last edited on
using statements expire. you can do this much more cleanly:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>


int main()
{
    code;

    { //this represents having like 100 cin/cout statements or something where std:: would be tedious bloat
       using std::cout; //good! or at least "not bad"
       using std::cin;  //good!
       cout << "Hello World!" << '\n';
    } //using statements are deactivated here. 

    more code;
}


and, preprocessors are direct replacements. if you had a small header file 'usingiostream.h' it could have using cin/cout/endl/formatting crap/etc all in one place and you get
1
2
3
4
5
6
7
8
int main()
{
    ...
     { #include "usingiostream.h"
       cin, cout, endl, setw, whatever all activated here
     } //all expire 
    ...
}


This stuff is purely style, conventions, and general 'we can do that, but should we?!' type discussions. You may want a .inc or some other extension for this kind of include that is not a real .h file. I use .inc for them, but its been a long time since I made one -- a lot of coders really, really hate the idea of this.
Last edited on
Ch1156 wrote:
I have another question about Chapter 6.12. It tells me all the stuff i already know about using namespace std; which i dont do, I use using std::cout; etc in global scope, however none of the examples have this form in there, the using std::cout is there but they put it in main, is it bad to put it in global scope?

As a general rule of thumb you normally should introduce names in as narrow scope as possible. In the global scope, using using-declarations (or even declaring your own variables or functions) has the same problem as using namespace std, only much much less because the number of names is much fewer.

But as always, it's a trade-off. If you repeat the same using-declarations in multiple functions you might want to put them outside instead and avoid the repetition.

The examples you see in that chapter are just that - examples. There isn't much need for using-declarations there (other than demonstrating how they work) and there is even less need for them to be in the global scope.

A quick glance at later chapters I don't see them actually using using-declarations anywhere. Personally I don't think it's worth it. It's normally much easier and more consistent to just type std:: everywhere in my opinion.
Last edited on
Thank you for the responses, ive decided to use std:: for now.
Topic archived. No new replies allowed.