Some clarifications

Hi all,

Let's explain the code below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct X
{
    static void f(); // declaration
    static int n;    // declaration
};
 
X g() { return X(); } // some function returning X
 
void f()
{
    X::f();  // X::f is a qualified name of static member function
    g().f(); // g().f is member access expression referring to a static member function
}
 
int X::n = 7; // definition
 
void X::f() // definition 
{ 
    n = 1; // X::n is accessible as just n in this scope
}


1- X g() is an independent normal function, but what does X() mean, as its return value? Is it an object of struct X, and then using that return value we can access members of the struct X?


2- Is void f() an independent normal function too and it has nothing to do with the struct X's static member function void f()? If so, what is X::f() inside that function doing? Is it simply calling the struct X's f() function?

3- The line int X::n = 7; is firstly needed to be able to use the static member variable n. Right? But what if we leave it this way: int X::n; ?
Last edited on
what does X() mean, as its return value?

It means construct a temporary object of type X (using the default constructor).

Is void f() an independent normal function too and it has nothing to do with the struct X's static member function void f()?

Yes. The two functions are independent.

If so, what is X::f() inside that function doing? Is it simply calling the struct X's f() function?

Yes. The code on lines 18-20 will be executed.

what if we leave it this way: int X::n; ?

It will get the value zero, because all static variables are zero-initialized before any other initialization takes place.
Thanks Peter for your answers.

It means construct a temporary object of type X (using the default constructor).

And then we can make use of the return value of the get() function to access the X class's members, yeah? So that "temporary" means we have no standalone object to use it for our tasks but using the return value of get, each time we need that accessibility, we use the members of the X class. Right?


all static variables are zero-initialized

Is it true for other non-int values too, for instance a char or string?
Last edited on
char is an int.
all (not just static) strings are initialized to empty string.
double statics will be zeroed.
static class variables will vary, via constructors and such. But basic types will be zeroed (at the byte level, generally, note that 0x00000 etc is 0 for doubles and ints). Bools accept 0 as false. Etc.
frek wrote:
And then we can make use of the return value of the get() function to access the X class's members, yeah? So that "temporary" means we have no standalone object to use it for our tasks but using the return value of get, each time we need that accessibility, we use the members of the X class. Right?

You can either use the returned object directly

1
2
// your code
g().f()

or you can store it in a variable and then use it, possibly multiple times.

1
2
X x = g();
x.f();

I'm probably making it sound more complicated than it really is. A "temporary" is an object that has no name and will live until the end of the full expression. It's pretty much the same as returning an integer.

 
int g() { return 15011; }

The expression 15011 creates a temporary int which the function uses as its return value.

frek wrote:
Is it true for other non-int values too, for instance a char or string?

Yes, but after being zero-initialized the string will be initialized by a constructor. If you don't explicitly initialize the string the default constructor will be used which initializes the string to an empty string.

All variables with static storage duration (this includes all global variables, static data members and static local variables) will be zero-initialized this way, but I don't you need to worry too much about this zero-initialization stuff. Just initialize your non-class variables explicitly and you'll be fine.

jonnin wrote:
basic types will be zeroed (at the byte level, generally, note that 0x00000 etc is 0 for doubles and ints)

Zero-initialization does not necessary mean the bit pattern will be all zeros. With GCC and Clang on Linux (not sure about other platforms) the null value for a pointer to a data member will have the same bit pattern as -1 (all the bits set). It will nevertheless be set to null when zero-initialized, just like other pointers.

https://godbolt.org/z/3teRWA
Last edited on
That is neat, I did not know those were treated that much different from normal pointers.

Thank so much to both of you. I appreciate your help.
Topic archived. No new replies allowed.