Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Initialize pointer-to-struct declaration to an unnamed struct?

Reply
Thread Tools

Initialize pointer-to-struct declaration to an unnamed struct?

 
 
Victor Bazarov
Guest
Posts: n/a
 
      06-27-2007
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> On Jun 27, 2:33 am, "Victor Bazarov" <(E-Mail Removed)> wrote:
>>> The struct is just as static -- it's a global definition.

>> No, a temporary created for the purposes of initialising something is
>> definitely not static. It's temporary.

>
> I don't understand that. Maybe we are talking about different things?
> The struct will be initialized at compile-time, and so will live
> "forever". How is that temporary?


In the statement

T obj = someexpression;

(provided it appears at the namespace scope) 'obj' has static storage
duration, but whatever 'someexpression' returns does NOT have static
storage duration, it's a temporary. That's significantly different
from

char const* p = "blah";

where the string literal ("blah") has static storage duration.

>
>> <shrug> Don't name them. Have an array and get pointers to its
>> elements:

>
> Bookkeeping array indexes isn't much better. And dynamically creating
> them would add overhead, etc.
>
> On Jun 27, 12:03 pm, James Kanze <(E-Mail Removed)> wrote:
>> In such cases, I usually define the data in a simple text file,
>> and then write a small program to convert it into legal C++.

>
> Yeah, if that's the case, for big definitions I'll probably go with a
> custom preprocessor, possibly outputting binary directly (which would
> also rid me of unclear handling of union initialization by VC6... but
> maybe that's the problem; using an old compiler.)
>
> Too bad C/++ doesn't offer (in many cases) such terseness as that
> possible by, say, JavaScript.


Huh? Terseness?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


 
Reply With Quote
 
 
 
 
Ehud Shapira
Guest
Posts: n/a
 
      06-27-2007
On Jun 27, 5:23 pm, "Victor Bazarov" <(E-Mail Removed)> wrote:
> T obj = someexpression;
>
> (provided it appears at the namespace scope) 'obj' has static storage
> duration, but whatever 'someexpression' returns does NOT have static
> storage duration, it's a temporary.

If (someexpression) is (a + b) then I can see how it's temporary, but
what's temporary about a struct defined at compile-time? Just like a
string, it would have a memory address and content defined before any
instruction is executed.

> Huh? Terseness?

Stuff like:

b = [
{ k:1, l:2, m:[ { i:0, j:1 } ] }
];

 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      06-27-2007
Ehud Shapira wrote:
> On Jun 27, 5:23 pm, "Victor Bazarov" <(E-Mail Removed)> wrote:
>> T obj = someexpression;
>>
>> (provided it appears at the namespace scope) 'obj' has static storage
>> duration, but whatever 'someexpression' returns does NOT have static
>> storage duration, it's a temporary.

> If (someexpression) is (a + b) then I can see how it's temporary, but
> what's temporary about a struct defined at compile-time? Just like a
> string, it would have a memory address and content defined before any
> instruction is executed.


There is no such concept in C++ as "struct defined at compile time".
Taking an address requires an l-value. To define an l-value, you need
to define a *named* object or an element/subobject of an array/another
object.

>> Huh? Terseness?

> Stuff like:
>
> b = [
> { k:1, l:2, m:[ { i:0, j:1 } ] }
> ];


How does that relate to your problem? You're trying to initialise
a pointer with an address of a temporary.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


 
Reply With Quote
 
Rolf Magnus
Guest
Posts: n/a
 
      06-28-2007
Ehud Shapira wrote:

> On Jun 27, 5:23 pm, "Victor Bazarov" <(E-Mail Removed)> wrote:
>> T obj = someexpression;
>>
>> (provided it appears at the namespace scope) 'obj' has static storage
>> duration, but whatever 'someexpression' returns does NOT have static
>> storage duration, it's a temporary.

> If (someexpression) is (a + b) then I can see how it's temporary, but
> what's temporary about a struct defined at compile-time?


The C++ standard says that it is one.

> Just like a string, it would have a memory address and content defined
> before any instruction is executed.


When will the destructor be executed?

 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      06-28-2007
On Jun 27, 5:19 pm, (E-Mail Removed) wrote:
> On Jun 27, 2:33 am, "Victor Bazarov" <(E-Mail Removed)> wrote:


> >> The struct is just as static -- it's a global definition.

> > No, a temporary created for the purposes of initialising something is
> > definitely not static. It's temporary.


> I don't understand that. Maybe we are talking about different things?
> The struct will be initialized at compile-time, and so will live
> "forever". How is that temporary?


At present, an object created as part of an initialization
expression is a temporary, it's destructor is called and the
memory it allocates is freed as soon as the initialization is
finished. Thus, for example, you could get the code to pass the
compiler by declaring constructors for the referred to struct's,
and defining an operator&() in them which returned the this
pointer. All you'd end up with, however, is dangling pointers.

Of course, if C++ added some special syntax to support such
things, a la C, then the lifetime of the objects would be
whatever C++ decided for those types of objects---in C, they
have static lifetime. (But C isn't C++, and such compound
initializers for a static object must have static initialization
themselves.)

> > <shrug> Don't name them. Have an array and get pointers to its
> > elements:


> Bookkeeping array indexes isn't much better. And dynamically creating
> them would add overhead, etc.


> On Jun 27, 12:03 pm, James Kanze <(E-Mail Removed)> wrote:


> > In such cases, I usually define the data in a simple text file,
> > and then write a small program to convert it into legal C++.


> Yeah, if that's the case, for big definitions I'll probably go with a
> custom preprocessor, possibly outputting binary directly (which would
> also rid me of unclear handling of union initialization by VC6... but
> maybe that's the problem; using an old compiler.)


I'm not sure what the problem is in VC++, but C++ doesn't have
designaged initializers either, and so you can only initialize
the first element of a union.

> Too bad C/++ doesn't offer (in many cases) such terseness as that
> possible by, say, JavaScript.


The languages are designed to meet different goals. I'd
certainly not want to develop anything really large in
JavaScript. A bit of redundancy is necessary when trying to get
different people, or even just separately compiled modules, to
work together.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

 
Reply With Quote
 
Ehud Shapira
Guest
Posts: n/a
 
      06-28-2007
On Jun 28, 1:05 pm, James Kanze <(E-Mail Removed)> wrote:
> At present, an object created as part of an initialization
> expression is a temporary, it's destructor is called and the
> memory it allocates is freed as soon as the initialization is
> finished.


Thanks for clearing that up a bit. So the scope of the object/
sub-struct would be the initialization block, and since that
doesn't make sense, anonymous recursive objects aren't allowed?

How's that behavior useful for anything? I'd expect the scope
to be that of the containing parent.

> I'm not sure what the problem is in VC++, but C++ doesn't have
> designaged initializers either, and so you can only initialize
> the first element of a union.


Yes, it expects the type of the first union member. (Which I
find an unclear limitation; the whole idea of a union is to
hold any of its types. [I also see the {.union_member = 1}
syntax unnecessarily verbal]).

But what's odd is that the first array element does accept a
non-first type, and only later array elements result in
compiler complaints.

> The languages are designed to meet different goals. I'd
> certainly not want to develop anything really large in
> JavaScript.


I'm not suggesting to use JS for "real" programming, but some
syntax possiblities are nice, and I think could work in C++
without conflicting with its syntax.

I guess C++ does pick up some things from here and there (like
C), and has quite possibly improved already; maybe I'm just not
seeing it w/ VC6.

Victor Bazarov:
>How does that relate to your problem? You're trying to
>initialise a pointer with an address of a temporary.


No. I was trying to initialize a hierarchial piece of data
in a concise and clean way.

Rolf Magnus:
>> Just like a string, it would have a memory address and content defined
>> before any instruction is executed.

>When will the destructor be executed?


The scope of the parent initialization is global, so I didn't
expect any freeing to be necessary.

 
Reply With Quote
 
Ehud Shapira
Guest
Posts: n/a
 
      06-28-2007
On Jun 28, 1:05 pm, James Kanze <(E-Mail Removed)> wrote:
> At present, an object created as part of an initialization
> expression is a temporary, it's destructor is called and the
> memory it allocates is freed as soon as the initialization is
> finished.


Thanks for clearing that up a bit. So the scope of the object/
sub-struct would be the initialization block, and since that
doesn't make sense, anonymous recursive objects aren't allowed?

How's that behavior useful for anything? I'd expect the scope
to be that of the containing parent.

> I'm not sure what the problem is in VC++, but C++ doesn't have
> designaged initializers either, and so you can only initialize
> the first element of a union.


Yes, it expects the type of the first union member. (Which I
find an unclear limitation; the whole idea of a union is to
hold any of its types. [I also see the {.union_member = 1}
syntax unnecessarily verbal]).

But what's odd is that the first array element does accept a
non-first type, and only later array elements result in
compiler complaints.

> The languages are designed to meet different goals. I'd
> certainly not want to develop anything really large in
> JavaScript.


I'm not suggesting to use JS for "real" programming, but some
syntax possiblities are nice, and I think could work in C++
without conflicting with its syntax.

I guess C++ does pick up some things from here and there (like
C), and has quite possibly improved already; maybe I'm just not
seeing it w/ VC6.

Victor Bazarov:
>How does that relate to your problem? You're trying to
>initialise a pointer with an address of a temporary.


No, I was after initializing a hierarchial piece of data
concisely and cleanly.

Rolf Magnus:
>> Just like a string, it would have a memory address and content
>> defined before any instruction is executed.

>When will the destructor be executed?


The scope of the parent initialization is global, so I didn't
expect any freeing to be necessary.

 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      06-29-2007
On Jun 28, 11:01 pm, Ehud Shapira <(E-Mail Removed)> wrote:
> On Jun 28, 1:05 pm, James Kanze <(E-Mail Removed)> wrote:


> > At present, an object created as part of an initialization
> > expression is a temporary, it's destructor is called and the
> > memory it allocates is freed as soon as the initialization is
> > finished.


> Thanks for clearing that up a bit. So the scope of the object/
> sub-struct would be the initialization block, and since that
> doesn't make sense, anonymous recursive objects aren't allowed?


I don't think that's the issue. If I write something at
namespace scope like:

std::string s( str1 + str2 ) ;

where str1 and str2 are also strings, the operator+ returns a
temporary, which will be destructed once the initialization has
finished (supposing no RVO, which would merge the return value
and the object being constructed).

> How's that behavior useful for anything? I'd expect the scope
> to be that of the containing parent.


See above. The problem is that we're discussing something that
isn't currently present in C++, and trying to assimilate it to
features that are. For example, one way to get your code to
compile would be to provide constructors for the sub-object,
and---since you can't use the built-in operator & on a
temporary, a user defined operator & which returns this. The
problem is that as far as the compiler is concerned, this is
exactly like the case with string, above---the constructed
object et al. is just there to get the initial value, which will
end up in the actual declared object. And all of the
intermediate values will be destructed, and the memory for them
freed.

One possibility would be to give the hierarchial elements
constructors, then write something like:

st_b c =
{
{ 1, 2, new st_a( 0, 1 ) },
{ 3, 4, new st_a( 0, 2 ) },
// ...
} ;

> > I'm not sure what the problem is in VC++, but C++ doesn't have
> > designaged initializers either, and so you can only initialize
> > the first element of a union.


> Yes, it expects the type of the first union member. (Which I
> find an unclear limitation; the whole idea of a union is to
> hold any of its types. [I also see the {.union_member = 1}
> syntax unnecessarily verbal]).


So how else would you choose. C90 says you can only initialize
the first element. C99 decided that this was overly
restrictive, and (for that and other reasons) introduced
designated initializers. What other syntax would you suggest?

In C++, you can initialize the element you want by using a
constructor.

> But what's odd is that the first array element does accept a
> non-first type, and only later array elements result in
> compiler complaints.


You've confused me here. Could you give an example.

[...]
> Victor Bazarov:


> >How does that relate to your problem? You're trying to
> >initialise a pointer with an address of a temporary.


> No, I was after initializing a hierarchial piece of data
> concisely and cleanly.


Yes and no. You were trying to define several distinct objects
of different types in a single definition statement. That just
doesn't exist in C++; you can only define a single object with
static lifetime in each declarator. Any other objects created
by the initialization expression are temporaries, or if you use
the operator new, dynamically allocated.

> Rolf Magnus:


> >> Just like a string, it would have a memory address and content
> >> defined before any instruction is executed.

> >When will the destructor be executed?


> The scope of the parent initialization is global, so I didn't
> expect any freeing to be necessary.


It probably isn't. I don't delete my singletons either.

The C solution gives static initialization and static lifetime.
Using new in C++ gives dynamic initialization and dynamic
lifetime. If the objects have a POD type, you never delete
them, and they are created during initialization of static
objects, their effective lifetime is the same as if they were
static. But the initialization remains dynamic; if you use the
objects in the constructors of other static objects, you are
likely to run into order of construction problems.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

 
Reply With Quote
 
Ehud Shapira
Guest
Posts: n/a
 
      06-29-2007
On Jun 29, 12:11 pm, James Kanze <(E-Mail Removed)> wrote:
>> So the scope of the object/sub-struct would be the initialization
>> block, and since that doesn't make sense, anonymous recursive
>> objects aren't allowed?

> I don't think that's the issue. If I write something at
> namespace scope like:
>
> std::string s( str1 + str2 ) ;


But here there's a ctor (and computation), so a temporary would make
sense. My deceleration had neither.

> The problem is that we're discussing something that
> isn't currently present in C++,


That's what I now understand. What I used was initializing multiple
flat arrays and linkings them by their names. I don't want dynamic
initialization; I'd rather have static data static.

>> Yes, it expects the type of the first union member. (Which I
>> find an unclear limitation; the whole idea of a union is to
>> hold any of its types. [I also see the {.union_member = 1}
>> syntax unnecessarily verbal]).

> So how else would you choose...
> What other syntax would you suggest?


The most logical thing would be to accept any type the union can hold.
If it's both an int and float, I shouldn't have to cast either.

As for .member, it seems I was mistaken. Naming members on
initialization isn't required, it's just another option. (Looks like
it might also be allowed to initialize a single object with a mix of
named and unnamed, for easy skipping of members, which is nice. But I
can't check all that on my compiler).

>> But what's odd is that the first array element does accept a
>> non-first type, and only later array elements result in
>> compiler complaints.

> You've confused me here. Could you give an example.


Actually, I misinterpreted the reason why an initializer of a union
(which is part of an array) worked even though its type was not the
same as the first union member. It wasn't about being the first in
array, it seems. The compiler somehow accepts offsetof(st, m) as a
pointer when m is the first member of st.

> Using new in C++ gives dynamic initialization and dynamic
> lifetime. If the objects have a POD type, you never delete
> them, and they are created during initialization of static
> objects, their effective lifetime is the same as if they were
> static. But the initialization remains dynamic;


Do you mean ones declared without "new"? If they're practically
static, why would they have to be created dynamically?

Checking the compiled code of a simple test, it seems a global
initialized struct is really static; it has a static address (no
indirection) and the data is preinitialized.

 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      06-30-2007
On Jun 30, 1:07 am, Ehud Shapira <(E-Mail Removed)> wrote:
> On Jun 29, 12:11 pm, James Kanze <(E-Mail Removed)> wrote:


[...]
> >> Yes, it expects the type of the first union member. (Which I
> >> find an unclear limitation; the whole idea of a union is to
> >> hold any of its types. [I also see the {.union_member = 1}
> >> syntax unnecessarily verbal]).

> > So how else would you choose...
> > What other syntax would you suggest?


> The most logical thing would be to accept any type the union can hold.
> If it's both an int and float, I shouldn't have to cast either.


But that doesn't help choose which element is being initialized.
Consider:

union U
{
double d1 ;
double d2 ;
} u = 3.1415 ;

Which element is being initialized? Or

union U
{
long l ;
double d ;
} u = 42 ;

Which element is being initialized?
>
> > Using new in C++ gives dynamic initialization and dynamic
> > lifetime. If the objects have a POD type, you never delete
> > them, and they are created during initialization of static
> > objects, their effective lifetime is the same as if they were
> > static. But the initialization remains dynamic;


> Do you mean ones declared without "new"? If they're practically
> static, why would they have to be created dynamically?


At namespace scope:

int* p = new int ;

That's dynamic initialization, even if p has static lifetime.
(I'm talking here about the variable p, not about the object
created by new.) In general, unless the initializer is a
constant expression and the type of the data is POD,
initialization will be dynamic. So:

int i1 = 42 ; // static initialization...
std::string s( "abc" ) ; // dynamic initialization...
extern int f() ;
int i2 = f() ; // dynamic initialization...

> Checking the compiled code of a simple test, it seems a global
> initialized struct is really static; it has a static address (no
> indirection) and the data is preinitialized.


If the type is a POD (plain ordinary data---roughly speaking,
something you could do in C), and the initialization expression
is a constant, then initialization should be static.

The distinction can be important. Static initialization takes
place before any code you write is executed, and because it
doesn't involve code, it is automatically independant of
ordering considerations. Dynamic initialization occurs in an
undefined order (when in different translation units), and you
can get into trouble quickly counting on it. (Imagine in the
above that f() uses some static variable which is dynamically
initialized.)

--
James Kanze (Gabi Software) email: (E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Using-declaration or using-directive inside unnamed-namespace? Niels Dekker - no reply address C++ 1 04-27-2010 04:16 PM
if instance variable get initialize after assigning some values or after constructor then when does static variable get initialize Tony Morris Java 3 02-04-2006 08:39 AM
initialize array elements during declaration hyena Java 10 01-24-2005 10:21 PM
forward declaration for typedef of unnamed structs Jordi Vilar C++ 5 02-18-2004 09:41 PM
forward declaration for typedef of unnamed structs Jordi Vilar C Programming 5 02-18-2004 09:41 PM



Advertisments