When is a static data member defined?

S

Steven T. Hatton

In the following code, at what point is S::c fully defined?

#include <iostream>

using std::cout;
using std::endl;
using std::eek:stream;

class C {
int _v;
public:
C(const int& v)
:_v(v)
{}

ostream& print(ostream& out) const
{
return out << _v;
}
};

struct S {
static const C c;
};

const C S::c = C(42);

ostream& operator<<(ostream& out, const S& s)
{
s.c.print(out);
return out;
}


int main()
{
S s;
cout << s << endl;
return 0;
}

--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell
 
V

Victor Bazarov

Steven said:
In the following code, at what point is S::c fully defined?

#include <iostream>
[...]
const C S::c = C(42);
Here.

[...]
int main()
{
S s;
cout << s << endl;
return 0;
}

V
 
I

Ioannis Vranos

Steven said:
In the following code, at what point is S::c fully defined?

#include <iostream>

using std::cout;
using std::endl;
using std::eek:stream;

class C {
int _v;
public:
C(const int& v)
:_v(v)
{}

ostream& print(ostream& out) const
{
return out << _v;
}
};

struct S {
static const C c;
};

const C S::c = C(42);


Here.
 
S

Steven T. Hatton

Victor said:
Steven said:
In the following code, at what point is S::c fully defined?

#include <iostream>
[...]
const C S::c = C(42);

Here.

I agree. At what point is the memory (typically) allocated?
--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell
 
R

Ron Natalie

Steven said:
I agree. At what point is the memory (typically) allocated?

S::c is statically allocated. You don't know when it is allocated
other than it's there before it can be used. Typically, it's just
created when the program is loaded (i.e, before execution actually
starts).
 
S

Steven T. Hatton

Ron said:
S::c is statically allocated. You don't know when it is allocated
other than it's there before it can be used. Typically, it's just
created when the program is loaded (i.e, before execution actually
starts).
I was speaking in terms used when discussing issues related to the use of
data members verses pointers or references to data members. For example,
if we have an indirect recursive structure such as:

#include <iostream>
class B;

class A{
B b;
};

class B{
A a;
};

It is commonly asserted that the above code will not compile because 'the
compiler doesn't know how to allocate the memory for b'. I guess that
means the compiler doesn't have sufficient information to determine the
relative offset for the end of the storage location intended to hold the
instance B A::b; So my question might be rephrased: when is the memory
allocation determined for the static data member?
--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell
 
R

Ron Natalie

Steven said:
It is commonly asserted that the above code will not compile because 'the
compiler doesn't know how to allocate the memory for b'.

It knows how, it just doesn't know how much :). Non-static members
must be of complete types, 9.2/8.
So my question might be rephrased: when is the memory
allocation determined for the static data member?

At the point of definition. It's declaration in the class is
allowed to be an incomplete type. See 9.4.2/2. The definition
(where you have const C S::c = C(42);) does require the complete
type.
 
V

Victor Bazarov

Steven said:
Ron Natalie wrote:



I was speaking in terms used when discussing issues related to the use of
data members verses pointers or references to data members. For example,
if we have an indirect recursive structure such as:

#include <iostream>
class B;

class A{
B b;
};

class B{
A a;
};

It is commonly asserted that the above code will not compile because 'the
compiler doesn't know how to allocate the memory for b'. I guess that
means the compiler doesn't have sufficient information to determine the
relative offset for the end of the storage location intended to hold the
instance B A::b;

Right. The _size_ of the object is the problem here.
So my question might be rephrased: when is the memory
allocation determined for the static data member?

Memory allocation for any object is determined when the object has
a complete type.

V
 
S

Steven T. Hatton

Victor said:
Memory allocation for any object is determined when the object has
a complete type.

So, in the example I posted, that would be when the member declaration S::C
s is encountered in the struct definition.

Here's just something to think about:

#include <iostream>

using std::cout;
using std::endl;
using std::eek:stream;

class C {
int _v;
public:

C(const int& v = 0)
:_v(v)
{}

ostream& print(ostream& out) const
{
return out << _c._v << " " << _v;
}

static const C _c;
};


struct S {
static const C c;
};

const C S::c = C(42);

ostream& operator<<(ostream& out, const S& s)
{
s.c.print(out);
return out;
}


const C C::_c = C(1066);

int main()
{
S s;
cout << s << endl;
return 0;
}

--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell
 
V

Victor Bazarov

Steven said:
Victor Bazarov wrote:




So, in the example I posted, that would be when the member declaration S::C
s is encountered in the struct definition.

Here's just something to think about:

So, have _you_ thought about it?
#include <iostream>

using std::cout;
using std::endl;
using std::eek:stream;

class C {
int _v;
public:

C(const int& v = 0)
:_v(v)
{}

ostream& print(ostream& out) const
{
return out << _c._v << " " << _v;
}

static const C _c;

That's a declaration.
};


struct S {
static const C c;

That's another declaration.
};

const C S::c = C(42);

That's a definition. No problem. 'C' is a complete type.
ostream& operator<<(ostream& out, const S& s)
{
s.c.print(out);
return out;
}


const C C::_c = C(1066);

That's another definition. Again, no problem.
int main()
{
S s;
cout << s << endl;
return 0;
}

So I've thought about it. Now what?

V
 
S

Steven T. Hatton

Victor said:
So, have _you_ thought about it?


That's a declaration.

C is a complete type. So can we say C::_c is allocated at this point?

--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell
 
V

Victor Bazarov

Steven said:
Victor Bazarov wrote:




C is a complete type. So can we say C::_c is allocated at this point?

First of all, C is not a complete type until the closing curly brace is
encountered. So, no, it's not a complete type. Second, no, C::_c is not
allocated at that point. Any object is only allocated when it's _defined_
not when it's _declared_.

V
 
S

Steven T. Hatton

Victor said:
First of all, C is not a complete type until the closing curly brace is
encountered.

My eyes must be playing tricks on me.
Second, no, C::_c is not
allocated at that point. Any object is only allocated when it's _defined_
not when it's _declared_.

"Memory allocation for any object is determined when the object has
a complete type."

What about this?

int foo(int i) {
int x;
return x * i;
}
--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell
 
V

Victor Bazarov

Steven said:
Victor Bazarov wrote:




My eyes must be playing tricks on me.




"Memory allocation for any object is determined when the object has
a complete type."

Determination of memory allocation (the ability to allocate memory) and
the actual _act_ of allocating memory are two different things. You need
to be a bit clearer about what you ask.

Memory is allocated when a static or automatic object is defined. For
now we can probably leave dynamic objects alone.
What about this?

int foo(int i) {
int x;
return x * i;
}

What about it? As far as I can tell it produces undefined behaviour
because 'x' has indeterminate value.

V
 
A

Andre Kostur

My eyes must be playing tricks on me.

Care to elaborate?
"Memory allocation for any object is determined when the object has
a complete type."

What about this?

int foo(int i) {
int x;
return x * i;
}

What about it? You need to be clearer about what exactly you're
asking... when is the memory for x allocated, when is the memory for i
allocated, when is the memory for the returned int allocated, when is the
memory for the result of "x * i" allocated, how many lines does this
function have?
 
S

Steven T. Hatton

Victor said:
Determination of memory allocation (the ability to allocate memory) and
the actual _act_ of allocating memory are two different things. You need
to be a bit clearer about what you ask.

Memory is allocated when a static or automatic object is defined. For
now we can probably leave dynamic objects alone.


What about it? As far as I can tell it produces undefined behaviour
because 'x' has indeterminate value.

V

I really wasn't trying to play gotcha. I just found the example thought
provoking. I really don't understand the subtelties of compiling and
linking.

I can (I believe) compile the class with the static member declared, but not
compile the definition of the static member at the same time. I later link
the two compiled object files to get a fully functional class with its
static members. If I never use the static members, the code will (I
believe) compile and link just fine.
--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell
 
V

Victor Bazarov

Steven said:
[...]
I really wasn't trying to play gotcha. I just found the example thought
provoking. I really don't understand the subtelties of compiling and
linking.

I can (I believe) compile the class with the static member declared, but not
compile the definition of the static member at the same time. I later link
the two compiled object files to get a fully functional class with its
static members. If I never use the static members, the code will (I
believe) compile and link just fine.

Compilation and linking of static members of non-local classes is very
similar to that of any other global object, and, not surprisingly, any
function. If you just declare a function

void foo();

and never define it, it will compile and link fine as long as you don't
try to use the function.

I am not sure how this can be as daunting as you make us believe you see
it.

Victor
 
S

Steven T. Hatton

Victor said:
Compilation and linking of static members of non-local classes is very
similar to that of any other global object, and, not surprisingly, any
function. If you just declare a function

void foo();

and never define it, it will compile and link fine as long as you don't
try to use the function.

I am not sure how this can be as daunting as you make us believe you see
it.

Victor

We aren't talking about a function. IIRC, a function in C++ is specifically
_not_ an object in any sense of the word. I'm not really doubting that the
memory is allocated when the definition is compiled. I'm just wondering
how how the pieces are put together. In view of the fact that the point of
definition of a static member object of class type is where a constructor
will be invoked, it makes sense that it will be physically allocated when
that definition's object code representation is loaded.

After examining the object files emitted by the compiler for various builds,
I can see that if the static member is not used, it is not even present in
the object file containing the entry point.
--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,239
Members
46,828
Latest member
LauraCastr

Latest Threads

Top