Re: Is this a new syntax
"Alf P. Steinbach" <alfps@start.no> wrote in message
news:_4KdnR1G-rupla_VnZ2dnUVZ_rzinZ2d@posted.comnet...
* 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);
}
}