470,849 Members | 1,036 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,849 developers. It's quick & easy.

Is this a new syntax

Hi all
I am seeing the following code in one place

standalone line in some function ,

{
(void*) new (h) Class_Name(xip, virobj, type, true);
}

Does it make h an object of the Class_Name class
-Parag
Jun 27 '08 #1
9 1185
Alf P. Steinbach wrote:
>>{
(void*) new (h) Class_Name(xip, virobj, type, true);
}
The only thing you really know is that that code is most likely full
of bugs.

Sorry, that last assumes that it's written by an ordinary programmer.

It /could/ be that it's written by an expert.

But if not, then it's probably chock full of bugs.
I wonder a bit about the differentiation between ordinary and expert
programmer. Most probably there are not that many people around, that
use this syntax without the adequate knowledge. In fact I have never
seen any buggy implementation with this syntax.
At some locations it is really useful. E.g. STL containers can reserve
space for new elements without calling the standard constructor
immediately. As far as I remember std::vector works this way to deal
with the logical size versus the allocation size.
Or I have implemented a simple, highly efficient, Java like, immutable
string class, that takes only the memory footprint of char* per instance
and the string value plus two ints header per different string value
(reference counted).

So, the syntax is only rarely needed. But if so, it is very important.
It is something like a back door for special purposes to call the
constructor directly. Calling a destructor explicitly is not less
dangerous and looks quite normal.
Marcel
Jun 27 '08 #2

"Marcel Müller" <ne**********@spamgourmet.orgwrote in message
news:48**********************@newsspool1.arcor-online.net...
Alf P. Steinbach wrote:
>>>{
(void*) new (h) Class_Name(xip, virobj, type, true);
}

The only thing you really know is that that code is most likely full of
bugs.

Sorry, that last assumes that it's written by an ordinary programmer.

It /could/ be that it's written by an expert.

But if not, then it's probably chock full of bugs.

I wonder a bit about the differentiation between ordinary and expert
programmer. Most probably there are not that many people around, that use
this syntax without the adequate knowledge. In fact I have never seen any
buggy implementation with this syntax.
I agree. placement new is a component of non placement new too. its nothing
mysterious.
In fact non placement new is two distinct operations consisting of
allocating memory and calling placement new.
explaining "new" by decomposition of new into these two very different
components helps to explain its workings.
Its particularly nice as it reveals the transition from raw hardware into
the higher level realms of "type".

Also useful for smart pointers ...;-)

regards
Andy Little
Jun 27 '08 #3

"Alf P. Steinbach" <al***@start.nowrote in message
news:_4******************************@posted.comne t...
>* Marcel Müller:
>Alf P. Steinbach wrote:
>>>>{
(void*) new (h) Class_Name(xip, virobj, type, true);
}
>
The only thing you really know is that that code is most likely full of
bugs.

Sorry, that last assumes that it's written by an ordinary programmer.

It /could/ be that it's written by an expert.

But if not, then it's probably chock full of bugs.

I wonder a bit about the differentiation between ordinary and expert
programmer.

Experts know that they don't know all. The old definition of an expert is
one who has made almost every conveivable error in the field of expertise,
and learned from that. Still, also experts make mistakes, even /trivial/
newbie mistakes; the main difference is that they know it and that they
deal with it, and that they tend to more often choose paths that turn out
to not be dead-ends.

>Most probably there are not that many people around, that use this syntax
without the adequate knowledge. In fact I have never seen any buggy
implementation with this syntax.

Any buggy implementation of what?

Most uses of placement new are ill-conceived attempts at premature
optimization.

I have mostly only seen such uses of placement new, but that may be
because I don't usually delve into the innards of code that deals with
memory allocation proper (like std::vector code).

>At some locations it is really useful. E.g. STL containers can reserve
space for new elements without calling the standard constructor
immediately.

STL containers are implemented by experts and very very thoroughly tested,
so that ordinary programmers don't have to deal with the things they do
inside but can rely on the safe functionality that's exposed.

>As far as I remember std::vector works this way to deal with the logical
size versus the allocation size.
Or I have implemented a simple, highly efficient, Java like, immutable
string class, that takes only the memory footprint of char* per instance
and the string value plus two ints header per different string value
(reference counted).

I think that's an example of non-expert use, evil premature
micro-optimization using the most dangerous low-level tool available. At
least, it sounds like you're allocating 1 chunk storage for the string
data plus two ints, and rely on implicit knowledge (not dynamically
represented) in the carrier. If so, then in addition to possible
alignment bugs, that means that you /inefficiently/ have to dynamically
allocate some variable amount of storage for every different string, when
the cost of allocation is precisely what you try to avoid. ;-)

>So, the syntax is only rarely needed. But if so, it is very important.

Yes.

>It is something like a back door for special purposes to call the
constructor directly.

No, placement new doesn't call a constructor "directly". The constructor
arguments you pass are forwarded to a constructor, not passed directly as
in an ordinary function call. In between there's a lot going on,
including preparation of cleanup in the event that the constructor throws.
Not sure what you mean.

Below is some code and some asm interspersed at the significant line 42

Therein placement new doesnt do much just, returns the address to construct
at AFAICS.
And N.B its more obvious doing it this way than munging two types of errors
in standard new.
IOW this should help to see what exceptions can be thrown from nonplacemnt
new more clearly
thus unravelling yet another bob.

regards
Andy Little

BTW I dont think the standard explains this very well ! It makes it sound
awfully complicated....

#include <iostream>
#include <stdexcept>
#include <string>
#include <cstring>

struct my{

my()
: text(0)
{
std::cout << "Enter some text\n";
std::string str;
getline(std::cin,str);
if (str == "throw"){
throw std::logic_error("DUMMY! I TOLD YOU not to input \"throw\"");
}
text = new char [str.length()+1];
strcpy(text,str.c_str());
}
~my()
{
std::cout << "text = \"" << text << "\" in my dtor \n";
delete [] text;
}
private:
my (my const &);
my & operator = ( my const &);

char * text;

};

int main()
{
// (malloc guarantees alignment)
void * allocation = malloc(sizeof (my));
if(allocation != NULL){
//construct a my at allocation
// input at prompt "throw" to throw
my* pmy=0;
try{
pmy = new (allocation) my(); // Line 42
pmy->~my();
//ASM
; Line 42
mov esi, edi
mov DWORD PTR __$EHRec$[ebp+12], 1
call ??0my@@QAE@XZ ; my::my
; Line 43
mov esi, eax
mov BYTE PTR __$EHRec$[ebp+12], bl
mov DWORD PTR _pmy$17011[ebp], eax
call ??1my@@QAE@XZ ; my::~my
/// end ASM
pmy=0;
}
catch(std::exception & e){
std::cout << e.what();
if(pmy){
std::cout << " and throw... twas messy bad \n";
}else{
std::cout << ", ... but throw.. twas neat \n";
}
}
free(allocation);
}
}

Jun 27 '08 #4
On May 19, 7:09*pm, "Alf P. Steinbach" <al...@start.nowrote:
[snip]
Experts know that they don't know all. *The old definition of an expert is one
who has made almost every conveivable error in the field of expertise, and
learned from that.
Heh heh. So an expert is somebody who no longer adds strtok
to codes, but knows how to debug it when it's already there.
Socks
Jun 27 '08 #5
On 20 mai, 17:05, "kwikius" <a...@servocomm.freeserve.co.ukwrote:
"Alf P. Steinbach" <al...@start.nowrote in
messagenews:4v******************************@poste d.comnet...
* kwikius:
"Alf P. Steinbach" <al...@start.nowrote in message
>No, placement new doesn't call a constructor "directly". The
constructor arguments you pass are forwarded to a constructor, not
passed directly as in an ordinary function call. In between there's a
lot going on, including preparation of cleanup in the event that the
constructor throws.
Not sure what you mean.
In general it has to arrange for calling the corresponding deallocation
function when a constructor throws. For a custom allocation function this
is the only way that the corresponding custom deallocation function can be
implicitly called, and it implies that for this, the allocation function
argument(s) must be stored, and an exception handler set up.
Well I dont see the O.P. expression as *allocation*. IMO its
construction at a preallocated address.
The standard sees it as allocation; an operator new function is
an "allocator", and a new expression will always call an
allocator function. (IIRC, too, there was no indication in the
original posting as to the type of the argument to new, so we
don't know whether it was the default placement new or not.)

Of course, at a higher level, it is constructing an object at a
predetermined address.
Nevertheless I don't agree that its that difficult or experts
only.
I don't think that it's that difficult, but the need should
rarely present itself unless you're working on an implementation
of the basic library---in which case, you probably should be an
expert. In the past, of course, before the standard library
became widespread, most programmers had used it once or twice,
since most programmers had their own versions of something like
std::vector.

--
James Kanze (GABI Software) email:ja*********@gmail.com
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
Jun 27 '08 #6

"James Kanze" <ja*********@gmail.comwrote in message
news:c7**********************************@z24g2000 prf.googlegroups.com...
On 20 mai, 17:05, "kwikius" <a...@servocomm.freeserve.co.ukwrote:
Well I dont see the O.P. expression as *allocation*. IMO its
construction at a preallocated address.
The standard sees it as allocation; an operator new function is
an "allocator", and a new expression will always call an
allocator function. (IIRC, too, there was no indication in the
original posting as to the type of the argument to new, so we
don't know whether it was the default placement new or not.)
The arg name is "h". I guess h --HANDLE ==void * (IIRC) from MS Windows
GlobalAlloc or some such.

regards
Andy Little
Jun 27 '08 #7
On May 21, 1:03 am, "Alf P. Steinbach" <al...@start.nowrote:
* kwikius:
"Alf P. Steinbach" <al...@start.nowrote in message
news:4v******************************@posted.comne t...
* kwikius:
"Alf P. Steinbach" <al...@start.nowrote in message
No, placement new doesn't call a constructor "directly". The
constructor arguments you pass are forwarded to a constructor, not
passed directly as in an ordinary function call. In between there's a
lot going on, including preparation of cleanup in the event that the
constructor throws.
Not sure what you mean.
In general it has to arrange for calling the corresponding
deallocation function when a constructor throws. For a
custom allocation function this is the only way that the
corresponding custom deallocation function can be
implicitly called, and it implies that for this, the
allocation function argument(s) must be stored, and an
exception handler set up.
Well I dont see the O.P. expression as *allocation*. IMO its
construction at a preallocated address.
Hm, I see James has already answered this. But I think it
would be less than polite if I let that answer serve as my
own, with no genuine Alf-input on the matter. So.
Regarding the first sentence, terminology. In the standard's
sense it's an allocation. Although as usual I can't find that
directly in the standard (the standard is notoriously
deficient in defining its terminology, or even using a
consistent terminology!), as with other implicitly defined
terms you can't make sense of things without assuming this
definition. For example, §5.3.4/5 has the condition "When the
allocated object is an array". And §5.3.4/5 applies to
non-placement new-expressions as well as placement
new-expressions, and since something was "allocated", there
had to be something called an "allocation".
§3.7.3.1 gives all the details about allocator functions...
except the fact that they are spelled "operator new", and that
all "operator new" are allocator functions:-). The firsrt
paragraph of §3.7.3 does mention that operator new is the global
allocator function. But it's still not really explicit:
"allocator function" == "function named operator new", but as
you say, while the standard doesn't really make sense otherwise,
it doesn't come out and say so in so many words.
Regarding the second sentence, construction at a pre-allocated
address, I have to take exception to James' statement that "Of
course, at a higher level, it is constructing an object at a
predetermined address.". Perhaps James didn't mean "higher
level" but "at the end" or something like that.
Sort of. "A higher level" is really sloppy wording, because it
doesn't mean anything: a higher level of what? What I meant was
a higher level of abstraction. What you consider it doing at
the design level.
A placement new expression does in general not construct at a
predetermined address, because in general the allocation
function will really allocate, not just take a pointer
argument and return it as void*.
And in the OP's case
(void*) new (h) Class_Name(xip, virobj, type, true);
we don't know the type of the allocation function argument
(the 'h'), and we don't know the definition of 'Class_Name',
more precisely, whether it has a custom allocation function,
and so in two different ways we don't know what the effect of
the placement new expression is.
In fact, all we know is that the programmer probably wasn't too
sure of what he was doing, since he felt obliged to cast the
results of the new expression to void*. I can't think of any
case where that would be appropriate (and if it were, I'd
definitely use static_cast, because it's rare enough that I'd
want to call attention to the fact).

Which sort of confirms your conclusion that the code wasn't
written by an expert.

--
James Kanze (GABI Software) email:ja*********@gmail.com
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
Jun 27 '08 #8

"James Kanze" <ja*********@gmail.comwrote in message
news:8a**********************************@m36g2000 hse.googlegroups.com...
On May 21, 1:03 am, "Alf P. Steinbach" <al...@start.nowrote:

<...>
And in the OP's case
(void*) new (h) Class_Name(xip, virobj, type, true);
we don't know the type of the allocation function argument
(the 'h'), and we don't know the definition of 'Class_Name',
more precisely, whether it has a custom allocation function,
and so in two different ways we don't know what the effect of
the placement new expression is.

In fact, all we know is that the programmer probably wasn't too
sure of what he was doing, since he felt obliged to cast the
results of the new expression to void*. I can't think of any
case where that would be appropriate (and if it were, I'd
definitely use static_cast, because it's rare enough that I'd
want to call attention to the fact).

Which sort of confirms your conclusion that the code wasn't
written by an expert.

if you do

#define HANDLE void*

HANDLE h1 = (HANDLE) new (h) Class_Name(xip, virobj, type, true);
/*...*/
SetProp( hMyWindow,"MyProp",h1); // Set a generic window property

then the code looks pretty much like a lot of other stuff in the windows
SDK source. C-style casts are the only casts used.

Its up to you whether you wish to call the Windows SDK authors experts or
not (I would say yes), but the SDK is written in C and that works very well
because as we all know the C++ ABI is not portable between compilers.

I read the use of the C-style cast as a statement along the lines of "OK
back to the C ABI" and I use it myself in that sense.

regards
Andy Little



Jun 27 '08 #9

"Alf P. Steinbach" <al***@start.nowrote in message
news:td******************************@posted.comne t...
>* kwikius:
<...>
>if you do

#define HANDLE void*

HANDLE h1 = (HANDLE) new (h) Class_Name(xip, virobj, type, true);
/*...*/
SetProp( hMyWindow,"MyProp",h1); // Set a generic window property

then the code looks pretty much like a lot of other stuff in the windows
SDK source. C-style casts are the only casts used.

Its up to you whether you wish to call the Windows SDK authors experts or
not (I would say yes), but the SDK is written in C

Hm, the SDK is written in C, and the C++ statement looks like that.

This is interesting... :-)
Well I guess you are being sarcastic. Otherwise I don't know what you mean.
Anyway Open up <windows.hand you will see all the API calls are C calls.
OTOH you are referring to not using ::SetProp? Sure I use global scope op
for C API calls. Its a nitpick for the example.

<..>
>and that works very well because as we all know the C++ ABI is not
portable between compilers.

Windows defines a fairly portable, but limited, C++ ABI, namely COM.
Now it has been superceded by .NET AFAIK which does have a portable ABI
among languages anyawy.
>I read the use of the C-style cast as a statement along the lines of "OK
back to the C ABI" and I use it myself in that sense.

Presumably in this context the cast was used to shut up an overzealous
compiler that insists on warning about just about everything, but an
alternative explanation is a coding guideline where the cast indicates
"this value is intentionally discarded", i.e. that not storing that
pointer is intentional.
I assumed that code was snipped omitting an assignment else cast seems
pretty pointless.
As I say I find C-style cast useful to document code for Windows API.

regards
Andy Little


Jun 27 '08 #10

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

699 posts views Thread by mike420 | last post: by
22 posts views Thread by Tuang | last post: by
14 posts views Thread by Sandy Norton | last post: by
16 posts views Thread by George Sakkis | last post: by
23 posts views Thread by Carter Smith | last post: by
19 posts views Thread by Nicolas Fleury | last post: by
4 posts views Thread by Jeremy Yallop | last post: by
177 posts views Thread by C# Learner | last post: by
4 posts views Thread by Bob hotmail.com> | last post: by
3 posts views Thread by Manuel | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.