By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,474 Members | 966 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,474 IT Pros & Developers. It's quick & easy.

When is a static data member defined?

P: n/a
In the following code, at what point is S::c fully defined?

#include <iostream>

using std::cout;
using std::endl;
using std::ostream;

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

Jul 22 '05 #1
Share this Question
Share on Google+
24 Replies


P: n/a
Steven T. Hatton wrote:
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
Jul 22 '05 #2

P: n/a
Steven T. Hatton wrote:
In the following code, at what point is S::c fully defined?

#include <iostream>

using std::cout;
using std::endl;
using std::ostream;

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.

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 22 '05 #3

P: n/a
Victor Bazarov wrote:
Steven T. Hatton wrote:
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

Jul 22 '05 #4

P: n/a
Steven T. Hatton wrote:

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).
Jul 22 '05 #5

P: n/a
Ron Natalie wrote:
Steven T. Hatton wrote:

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).

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

Jul 22 '05 #6

P: n/a
Steven T. Hatton wrote:

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.
Jul 22 '05 #7

P: n/a
Steven T. Hatton wrote:
Ron Natalie wrote:

Steven T. Hatton wrote:

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).


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
Jul 22 '05 #8

P: n/a
Victor Bazarov wrote:
Steven T. Hatton wrote:
> 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.


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::ostream;

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

Jul 22 '05 #9

P: n/a
Steven T. Hatton wrote:
Victor Bazarov wrote:

Steven T. Hatton wrote:
> 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.

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::ostream;

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
Jul 22 '05 #10

P: n/a
Victor Bazarov wrote:
Steven T. Hatton wrote:
Victor Bazarov wrote:

Steven T. Hatton wrote:
> 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.

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::ostream;

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.
};


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

Jul 22 '05 #11

P: n/a
Steven T. Hatton wrote:
Victor Bazarov wrote:

Steven T. Hatton wrote:
Victor Bazarov wrote:

Steven T. Hatton wrote:

> 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.
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::ostream;

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.

};

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
Jul 22 '05 #12

P: n/a
Victor Bazarov wrote:
Steven T. Hatton wrote:
Victor Bazarov wrote:

Steven T. Hatton wrote:

Victor Bazarov wrote:

>Steven T. Hatton wrote:
>
>> 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.
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::ostream;

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.
};

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.


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

Jul 22 '05 #13

P: n/a
Steven T. Hatton wrote:

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


No, we say it is defined.
Jul 22 '05 #14

P: n/a
Steven T. Hatton wrote:
Victor Bazarov wrote:

Steven T. Hatton wrote:

Victor Bazarov wrote:

Steven T. Hatton wrote:
>Victor Bazarov wrote:
>
>
>
>
>>Steven T. Hatton wrote:
>>
>>
>>>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.
>
>
>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::ostream;
>
>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.

>};
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.

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."


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
Jul 22 '05 #15

P: n/a
Ron Natalie wrote:
Steven T. Hatton wrote:

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


No, we say it is defined.


Weird. I say it is declared.

V
Jul 22 '05 #16

P: n/a
"Steven T. Hatton" <su******@setidava.kushan.aa> wrote in
news:6b********************@speakeasy.net:
Victor Bazarov wrote:
Steven T. Hatton wrote:
Victor Bazarov wrote:
Steven T. Hatton wrote:

>Victor Bazarov wrote:
>
>
>
>>Steven T. Hatton wrote:
>>
>>> 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.
>
>
>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::ostream;
>
>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.
>};
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.


My eyes must be playing tricks on me.


Care to elaborate?
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;
}


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?
Jul 22 '05 #17

P: n/a
Victor Bazarov wrote:
Steven T. Hatton wrote:
Victor Bazarov wrote:

Steven T. Hatton wrote:
Victor Bazarov wrote:

>Steven T. Hatton wrote:
>
>
>>Victor Bazarov wrote:
>>
>>
>>
>>
>>>Steven T. Hatton wrote:
>>>
>>>
>>>>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.
>>
>>
>>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::ostream;
>>
>>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.
>
>
>
>>};
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.

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."


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


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

Jul 22 '05 #18

P: n/a
Steven T. Hatton wrote:
[...]
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
Jul 22 '05 #19

P: n/a
Victor Bazarov wrote:
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

Jul 22 '05 #20

P: n/a
Steven T. Hatton wrote:
Here's just something to think about:


[...]
Here is an interesting side effect:

#include <iostream>

class C {
int v;
public:

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

static const C c;
};

const C C::c = 1066;

int main()
{
using std::cout;
using std::endl;

C obj;

cout<<&obj.c<<endl;

cout<<&obj.c.c<<endl;

cout<<&obj.c.c.c<<endl;

}
All c here are the same static object. Interesting.

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 22 '05 #21

P: n/a
Steven T. Hatton <su******@setidava.kushan.aa> wrote:
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.


Since I am not a language lawyer I am positive I will be corrected
promptly. Since C++ implementations are allowed to defer the
contructions of objects defined in a given translation unit until the
first use of any object or function defined in the translation unit it
would not suprise me at all if a compiler 'optimized' it away in this
circumstance. I do not know the "legal" wording of it but I believe it
is referred to as lazy evaluation and in spirit of the Golden Rule of C++
- you don't pay for something you don't use. That could be speed, size,
etc.

I do not know if this is technically correct as 'bible' though, just my
simple understanding.
--
Chris Johnson
~
~
:wq
Jul 22 '05 #22

P: n/a
Steven T. Hatton wrote:
Victor Bazarov wrote:

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.


Function is not an object. However, just like any other non-temporary
object, every [ordinary] function is designated by a name. When
a non-const object is declared in the namespace scope, its name has
external linkage, just like a function (unless otherwise specified).
That means they have some kind of symbol by which they are recognised
from another module (or translation unit).

If used anywhere, a symbol (name) has to be _defined_ exactly once (the
One Definition Rule) to make a well-formed program. If _not_ used
anywhere, a symbol does NOT have to be defined. See 3.2/3.
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.


Well, you're closer to understanding how this works, I trust. I am not
sure how we can help you further without going into the implementation
details. Perhaps if you find a book on compilers and linkers or talk to
people in a newsgroup for a particular implementation of the language,
you might learn more about that particular implementation or about how
to implement a language in general.

An example of something that is very common yet not considered part of the
language definition: virtual function mechanism implementation. On all
implementations I know it is done using a so called 'virtual function
table', a list of addresses of class functions is stored somewhere in
memory and a pointer to that table get stored in every object of that
class at the time of construction. Short name for that pointer/pointers
is 'vtbl'. Yet there is no mention of it in the Standard. Why? Because
it is considered an implementation detail. See why I am reluctant to go
into linking and how it works or should work?

V
Jul 22 '05 #23

P: n/a
Victor Bazarov wrote:
Steven T. Hatton wrote:
Victor Bazarov wrote:

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.


Function is not an object. However, just like any other non-temporary
object, every [ordinary] function is designated by a name. When
a non-const object is declared in the namespace scope, its name has
external linkage, just like a function (unless otherwise specified).
That means they have some kind of symbol by which they are recognised
from another module (or translation unit).

If used anywhere, a symbol (name) has to be _defined_ exactly once (the
One Definition Rule) to make a well-formed program. If _not_ used
anywhere, a symbol does NOT have to be defined. See 3.2/3.
> 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.


Well, you're closer to understanding how this works, I trust. I am not
sure how we can help you further without going into the implementation
details. Perhaps if you find a book on compilers and linkers or talk to
people in a newsgroup for a particular implementation of the language,
you might learn more about that particular implementation or about how
to implement a language in general.

An example of something that is very common yet not considered part of the
language definition: virtual function mechanism implementation. On all
implementations I know it is done using a so called 'virtual function
table', a list of addresses of class functions is stored somewhere in
memory and a pointer to that table get stored in every object of that
class at the time of construction. Short name for that pointer/pointers
is 'vtbl'. Yet there is no mention of it in the Standard. Why? Because
it is considered an implementation detail. See why I am reluctant to go
into linking and how it works or should work?

V


The virtual function table is discussed extensively in the TC++PL(SE). The
idea that it is not topical here is absurd.
--
"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

Jul 22 '05 #24

P: n/a
Steven T. Hatton wrote:
[...]
The virtual function table is discussed extensively in the TC++PL(SE). The
idea that it is not topical here is absurd.


I totally agree. Can you tell me who said it wasn't topical here (besides
you, that is)?
Jul 22 '05 #25

This discussion thread is closed

Replies have been disabled for this discussion.