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

please explain why this is Undefined Behavior

P: n/a
REH
Someone more articulate than me please explain to Ioannis Vranos why the
following two programs both exhibit undefined behavior:
#include <iostream>
#include <cstring>

class SomeClass
{
public:

double d;
int i;
float f;
long l;
};
int main()
{
using namespace std;

unsigned char array[sizeof(SomeClass)];

SomeClass obj= {1, 2, 3, 4};

memcpy(array, &obj, sizeof(obj));

SomeClass *p= reinterpret_cast<SomeClass *>(array);

cout<<p->d<<" "<<p->i<<" "<<p->f<<" "<<p->l<<"\n";
}


#include <iostream>
#include <cstring>

class SomeClass
{
public:

double d;
int i;
float f;
long l;
};
int main()
{
using namespace std;

unsigned char array[sizeof(SomeClass)];

SomeClass obj= {1, 2, 3, 4};

SomeClass *p= new(array)SomeClass(obj);

cout<<p->d<<" "<<p->i<<" "<<p->f<<" "<<p->l<<"\n";
}

Jul 23 '05 #1
Share this Question
Share on Google+
25 Replies


P: n/a
REH wrote:
Someone more articulate than me please explain to Ioannis Vranos why the
following two programs both exhibit undefined behavior:


What have you managed so far?
#include <iostream>
#include <cstring>

class SomeClass
{
public:

double d;
int i;
float f;
long l;
};
int main()
{
using namespace std;

unsigned char array[sizeof(SomeClass)];

SomeClass obj= {1, 2, 3, 4};

memcpy(array, &obj, sizeof(obj));

SomeClass *p= reinterpret_cast<SomeClass *>(array);
As I can see, 'obj' and 'array' have different alignment requirements.
Reinterpret-casting 'array' to 'obj' may violate hardware protocols for
loading values from multi-byte objects.

cout<<p->d<<" "<<p->i<<" "<<p->f<<" "<<p->l<<"\n";
}


#include <iostream>
#include <cstring>

class SomeClass
{
public:

double d;
int i;
float f;
long l;
};
int main()
{
using namespace std;

unsigned char array[sizeof(SomeClass)];

SomeClass obj= {1, 2, 3, 4};

SomeClass *p= new(array)SomeClass(obj);
Same thing here.

cout<<p->d<<" "<<p->i<<" "<<p->f<<" "<<p->l<<"\n";
}


You could fix that if you went

unsigned char *array = new unsigned char[sizeof(SomeClass)];

and then as it was. 'new' returns pointers properly aligned.

V
Jul 23 '05 #2

P: n/a
REH wrote:
Someone more articulate than me please explain to Ioannis Vranos why the
following two programs both exhibit undefined behavior:
#include <iostream>
#include <cstring>

class SomeClass
{
public:

double d;
int i;
float f;
long l;
};
I'm unsure of the more hairy end of the definition of "Plain Ole Data
Structure", but I feel safe calling that one.
int main()
{
using namespace std;

unsigned char array[sizeof(SomeClass)];

SomeClass obj= {1, 2, 3, 4};

memcpy(array, &obj, sizeof(obj));

SomeClass *p= reinterpret_cast<SomeClass *>(array);
Well-defined. reinterpret_cast is used on storage whose contents you know to
be the correct type.
cout<<p->d<<" "<<p->i<<" "<<p->f<<" "<<p->l<<"\n";
} int main()
{
using namespace std;

unsigned char array[sizeof(SomeClass)];

SomeClass obj= {1, 2, 3, 4};

SomeClass *p= new(array)SomeClass(obj);
Well-defined. obj got copy-constructed into a new object with a valid type
and valid storage.
cout<<p->d<<" "<<p->i<<" "<<p->f<<" "<<p->l<<"\n";
Down here, we need a matching ~delete. Right? Or does the POD make it not
needed? I would add it anyway and let the compiler throw it away.
}


--
Phlip
http://industrialxp.org/community/bi...UserInterfaces
Jul 23 '05 #3

P: n/a
REH

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:wi*******************@newsread1.mlpsca01.us.t o.verio.net...
REH wrote:
Someone more articulate than me please explain to Ioannis Vranos why the
following two programs both exhibit undefined behavior:
What have you managed so far?


That you cannot arbitrarily cast a char* to any other pointer, because of
alignment issues. But, I am right aren't I? This is undefined behavior.
#include <iostream>
#include <cstring>

class SomeClass
{
public:

double d;
int i;
float f;
long l;
};
int main()
{
using namespace std;

unsigned char array[sizeof(SomeClass)];

SomeClass obj= {1, 2, 3, 4};

memcpy(array, &obj, sizeof(obj));

SomeClass *p= reinterpret_cast<SomeClass *>(array);
As I can see, 'obj' and 'array' have different alignment requirements.
Reinterpret-casting 'array' to 'obj' may violate hardware protocols for
loading values from multi-byte objects.

cout<<p->d<<" "<<p->i<<" "<<p->f<<" "<<p->l<<"\n";
}


#include <iostream>
#include <cstring>

class SomeClass
{
public:

double d;
int i;
float f;
long l;
};
int main()
{
using namespace std;

unsigned char array[sizeof(SomeClass)];

SomeClass obj= {1, 2, 3, 4};

SomeClass *p= new(array)SomeClass(obj);
Same thing here.

cout<<p->d<<" "<<p->i<<" "<<p->f<<" "<<p->l<<"\n";
}


You could fix that if you went

unsigned char *array = new unsigned char[sizeof(SomeClass)];

and then as it was. 'new' returns pointers properly aligned.

V

Jul 23 '05 #4

P: n/a
[...]
int main()
{
using namespace std;

unsigned char array[sizeof(SomeClass)];

SomeClass obj= {1, 2, 3, 4};

SomeClass *p= new(array)SomeClass(obj);

Same thing here.

cout<<p->d<<" "<<p->i<<" "<<p->f<<" "<<p->l<<"\n";
}

You could fix that if you went

unsigned char *array = new unsigned char[sizeof(SomeClass)];

and then as it was. 'new' returns pointers properly aligned.


properly aligned regardless the different type, SomeClass here instead
of returned "new unsigned char[]"?

struct X
{
X(){}
~X(){}
};
void foo()
{
char buffer[1024];
X * x = new(buffer) X; // << undefined behaviour, because //
buffer resides on stack?
x->~X();
}
int main()
{
char * buffer = new char[1024];
X * x = new(buffer) X; // Ok? because ..
x->~X();
}

Did I got it right?

Thanks in advance

--Daniel
Jul 23 '05 #5

P: n/a
[...]
int main()
{
char * buffer = new char[1024];
X * x = new(buffer) X; // Ok? because ..
x->~X();
}


s malenkoi oshibkoi :)

delete [] buffer;

--Daniel
Jul 23 '05 #6

P: n/a
Victor Bazarov wrote:
You could fix that if you went

unsigned char *array = new unsigned char[sizeof(SomeClass)];

and then as it was. 'new' returns pointers properly aligned.

So are the following programs portable?

#include <iostream>
#include <cstring>

class SomeClass
{
public:

double d;
int i;
float f;
long l;
};
int main()
{
using namespace std;

unsigned char *parray= new unsigned char[sizeof(SomeClass)];

SomeClass obj= {1, 2, 3, 4};

memcpy(parray, &obj, sizeof(obj));

SomeClass *p= reinterpret_cast<SomeClass *>(parray);

//Continue using parray as SomeClass
cout<<p->d<<" "<<p->i<<" "<<p->f<<" "<<p->l<<"\n";

//Is this needed?
p->~SomeClass();

delete[] parray;
}


#include <iostream>
#include <cstring>

class SomeClass
{
public:

double d;
int i;
float f;
long l;
};
int main()
{
using namespace std;

unsigned char *parray= new unsigned char[sizeof(SomeClass)];

SomeClass obj= {1, 2, 3, 4};

SomeClass *p= new(parray)SomeClass(obj);

//Continue using parray as SomeClass
cout<<p->d<<" "<<p->i<<" "<<p->f<<" "<<p->l<<"\n";

//Is this needed?
p->~SomeClass();

delete[] parray;
}
--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #7

P: n/a
Daniel Schüle wrote:
[...]
void foo()
{
char buffer[1024];
X * x = new(buffer) X; // << undefined behaviour, because //
buffer resides on stack?
Not because on the stack but because there are no guarantees that
the alignment requirements are met.
x->~X();
}
int main()
{
char * buffer = new char[1024];
X * x = new(buffer) X; // Ok? because ..
Not OK. You had to obtain the 'buffer' pointer using sizeof(X).
x->~X();
}

Did I got it right?


Nope.

V
Jul 23 '05 #8

P: n/a
REH

"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in message
news:1112066299.898643@athnrd02...
Victor Bazarov wrote:
You could fix that if you went

unsigned char *array = new unsigned char[sizeof(SomeClass)];

and then as it was. 'new' returns pointers properly aligned.

So are the following programs portable?

#include <iostream>
#include <cstring>

class SomeClass
{
public:

double d;
int i;
float f;
long l;
};
int main()
{
using namespace std;

unsigned char *parray= new unsigned char[sizeof(SomeClass)];

SomeClass obj= {1, 2, 3, 4};

memcpy(parray, &obj, sizeof(obj));

SomeClass *p= reinterpret_cast<SomeClass *>(parray);

//Continue using parray as SomeClass
cout<<p->d<<" "<<p->i<<" "<<p->f<<" "<<p->l<<"\n";

//Is this needed?
p->~SomeClass();

delete[] parray;
}


#include <iostream>
#include <cstring>

class SomeClass
{
public:

double d;
int i;
float f;
long l;
};
int main()
{
using namespace std;

unsigned char *parray= new unsigned char[sizeof(SomeClass)];

SomeClass obj= {1, 2, 3, 4};

SomeClass *p= new(parray)SomeClass(obj);

//Continue using parray as SomeClass
cout<<p->d<<" "<<p->i<<" "<<p->f<<" "<<p->l<<"\n";

//Is this needed?
p->~SomeClass();

delete[] parray;
}
--
Ioannis Vranos


They are portable because new (and malloc, et. al.) guarantee the memory
returned will properly alignment for any type. I prefer to just union the
array with a variable of the type with the greatest alignment requirement in
the system, there by avoiding heap allocation altogether. No, I don't think
the calls to the destructor are needed in this case because the type used is
a POD, but they don't hurt and will avoid issues in the future if they type
ever changes. Also, if the type changes to a non-POD, the memcpy becomes
non-portable.

REH
Jul 23 '05 #9

P: n/a
Ioannis Vranos wrote:
Victor Bazarov wrote:
You could fix that if you went

unsigned char *array = new unsigned char[sizeof(SomeClass)];

and then as it was. 'new' returns pointers properly aligned.

So are the following programs portable?


Strictly speaking, no, because they access members of the object
through a pointer that isn't a pointer to the original object.
'reinterpret_cast' is said to only preserve the object if the pointer
(and the object) on a "round-trip". This is safe:

struct SomeClass { int a; double b; char c; };

SomeClass obj = { 1,2,3 };
char *ptr = reinterpret_cast<char*>(obj); // cast to unrelated ptr
SomeClass *p = reinterpret_cast<SomeClass*>(ptr); // cast back
(p->a == 1) // yields 'true'

V
Jul 23 '05 #10

P: n/a
REH wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:wi*******************@newsread1.mlpsca01.us.t o.verio.net...
REH wrote:
Someone more articulate than me please explain to Ioannis Vranos why the
following two programs both exhibit undefined behavior:


What have you managed so far?

That you cannot arbitrarily cast a char* to any other pointer, because of
alignment issues. But, I am right aren't I? This is undefined behavior.


You can cast a pointer to any type. The results are implementation
(compiler) defined. I don't believe that it is undefined behavior.
Casting char * to other pointer types is commonly performed in the
embedded systems arena, but that portion of the code is platform
specific.

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.comeaucomputing.com/learn/faq/
Other sites:
http://www.josuttis.com -- C++ STL Library book
http://www.sgi.com/tech/stl -- Standard Template Library
Jul 23 '05 #11

P: n/a
REH

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:8O********************@comcast.com...
Strictly speaking, no, because they access members of the object
through a pointer that isn't a pointer to the original object.
'reinterpret_cast' is said to only preserve the object if the pointer
(and the object) on a "round-trip". This is safe:

struct SomeClass { int a; double b; char c; };

SomeClass obj = { 1,2,3 };
char *ptr = reinterpret_cast<char*>(obj); // cast to unrelated ptr
SomeClass *p = reinterpret_cast<SomeClass*>(ptr); // cast back
(p->a == 1) // yields 'true'

V

So, even correcting for the alignment, it's still not portable? Only when
your original pointer is of the correct type, portability is acheived? Is
there no way to "allocate" a block of non-heap memory, and construct an
object in it. I thought that was what placement new provided you, and then
the only concern was alignment.
Jul 23 '05 #12

P: n/a
REH

"Thomas Matthews" <Th*************************@sbcglobal.net> wrote in
message news:CD******************@newssvr33.news.prodigy.c om...
REH wrote:
That you cannot arbitrarily cast a char* to any other pointer, because of alignment issues. But, I am right aren't I? This is undefined
behavior.
You can cast a pointer to any type. The results are implementation
(compiler) defined. I don't believe that it is undefined behavior.
Casting char * to other pointer types is commonly performed in the
embedded systems arena, but that portion of the code is platform
specific.

So, it is "implementation specific," not "undefined behavior." Thanks, I
will remember that.
Jul 23 '05 #13

P: n/a
[..]
int main()
{
char * buffer = new char[1024];
X * x = new(buffer) X; // Ok? because ..

Not OK. You had to obtain the 'buffer' pointer using sizeof(X).


would multiple of sizeof(X) also be right?

thnanks

-Daniel
Jul 23 '05 #14

P: n/a
REH wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:8O********************@comcast.com...

Strictly speaking, no, because they access members of the object
through a pointer that isn't a pointer to the original object.
'reinterpret_cast' is said to only preserve the object if the pointer
(and the object) on a "round-trip". This is safe:

struct SomeClass { int a; double b; char c; };

SomeClass obj = { 1,2,3 };
char *ptr = reinterpret_cast<char*>(obj); // cast to unrelated ptr
SomeClass *p = reinterpret_cast<SomeClass*>(ptr); // cast back
(p->a == 1) // yields 'true'

V


So, even correcting for the alignment, it's still not portable? Only when
your original pointer is of the correct type, portability is acheived? Is
there no way to "allocate" a block of non-heap memory, and construct an
object in it. I thought that was what placement new provided you, and then
the only concern was alignment.


You thought correctly. You can do

char *ptr = new char[sizeof(SomeClass)];

and then

SomeClass *p = new (ptr) SomeClass;

which will construct the object which will have the proper alignment.
The object will have to be later destroyed using the explicit d-tor
call syntax:

p->~SomeClass();

even if the d-tor is trivial or provided by the compiler.

What you shouldn't do is

char *ptr = new char[sizeof(SomeClass)];
SomeClass *p = reinterpret_cast<SomeClass*>(ptr);

at this point '*p' is not a properly constructed object. The result
of such conversion is unspecified and therefore not portable.

V
Jul 23 '05 #15

P: n/a
Daniel Schüle wrote:
[..]
int main()
{
char * buffer = new char[1024];
X * x = new(buffer) X; // Ok? because ..


Not OK. You had to obtain the 'buffer' pointer using sizeof(X).

would multiple of sizeof(X) also be right?

thnanks


I would assume so. In your original example sizeof(X) _could_ be
larger than 1024, there was no indication otherwise.

V
Jul 23 '05 #16

P: n/a
REH

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:2Q*******************@newsread1.mlpsca01.us.t o.verio.net...
REH wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:8O********************@comcast.com...

Strictly speaking, no, because they access members of the object
through a pointer that isn't a pointer to the original object.
'reinterpret_cast' is said to only preserve the object if the pointer
(and the object) on a "round-trip". This is safe:

struct SomeClass { int a; double b; char c; };

SomeClass obj = { 1,2,3 };
char *ptr = reinterpret_cast<char*>(obj); // cast to unrelated ptr
SomeClass *p = reinterpret_cast<SomeClass*>(ptr); // cast back
(p->a == 1) // yields 'true'

V


So, even correcting for the alignment, it's still not portable? Only when your original pointer is of the correct type, portability is acheived? Is there no way to "allocate" a block of non-heap memory, and construct an
object in it. I thought that was what placement new provided you, and then the only concern was alignment.


You thought correctly. You can do

char *ptr = new char[sizeof(SomeClass)];

and then

SomeClass *p = new (ptr) SomeClass;

which will construct the object which will have the proper alignment.
The object will have to be later destroyed using the explicit d-tor
call syntax:

p->~SomeClass();

even if the d-tor is trivial or provided by the compiler.

What you shouldn't do is

char *ptr = new char[sizeof(SomeClass)];
SomeClass *p = reinterpret_cast<SomeClass*>(ptr);

at this point '*p' is not a properly constructed object. The result
of such conversion is unspecified and therefore not portable.

V


Ah, OK, I misunderstood you. I thought you were saying both were not
portable. Thanks for the clarification.

REH
Jul 23 '05 #17

P: n/a
Victor Bazarov wrote:
You thought correctly. You can do

char *ptr = new char[sizeof(SomeClass)];

and then

SomeClass *p = new (ptr) SomeClass;

which will construct the object which will have the proper alignment.
The object will have to be later destroyed using the explicit d-tor
call syntax:

p->~SomeClass();

even if the d-tor is trivial or provided by the compiler.

What you shouldn't do is

char *ptr = new char[sizeof(SomeClass)];
SomeClass *p = reinterpret_cast<SomeClass*>(ptr);

at this point '*p' is not a properly constructed object. The result
of such conversion is unspecified and therefore not portable.

Very interesting stuff. However if you replace reinterpret_cast with:

SomeClass *p = static_cast<SomeClass *>( static_cast<void *>(ptr) );

is it guaranteed to always work?
Also, the standard says:

"For any object (other than a base-class subobject) of POD type T, whether or not the
object holds a valid value of type T, the underlying bytes (1.7) making up the object can
be copied into an array of char or unsigned char. If the content of the array of char or
unsigned char is copied back into the object, the object shall subsequently hold its
original value".
So in strict terms it looks like that only if we copy the bytes back, we get the same
object, and making an object in our bytes is not guaranteed to work.

The only examples I have seen in TC++PL3 for placement new, are in the style:
int x;

int *p= new(&x) int;

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #18

P: n/a
Ioannis Vranos wrote:
Victor Bazarov wrote:
You thought correctly. You can do

char *ptr = new char[sizeof(SomeClass)];

and then

SomeClass *p = new (ptr) SomeClass;

which will construct the object which will have the proper alignment.
The object will have to be later destroyed using the explicit d-tor
call syntax:

p->~SomeClass();

even if the d-tor is trivial or provided by the compiler.

What you shouldn't do is

char *ptr = new char[sizeof(SomeClass)];
SomeClass *p = reinterpret_cast<SomeClass*>(ptr);

at this point '*p' is not a properly constructed object. The result
of such conversion is unspecified and therefore not portable.
Very interesting stuff. However if you replace reinterpret_cast with:

SomeClass *p = static_cast<SomeClass *>( static_cast<void *>(ptr) );

is it guaranteed to always work?


Yes. The cast to void* is actually implicit, so static_cast is OK for
the inverse conversion (inversion). Which, of course, brings up a simple
question, why create such complication? Shouldn't it be allowed? BFD,
right? I don't know the answer beyond the fact that C used to do that
with its casts, and C++ tried to be safer and less error-prone in that
area.
Also, the standard says:

"For any object (other than a base-class subobject) of POD type T,
whether or not the object holds a valid value of type T, the underlying
bytes (1.7) making up the object can be copied into an array of char or
unsigned char. If the content of the array of char or unsigned char is
copied back into the object, the object shall subsequently hold its
original value".
IOW, if SomeClass is a POD, doing

SomeClass someobject;
char* temporary_storage = new char[sizeof(SomeClass)];
memcpy(temporary_storage, &someobject, sizeof(SomeClass));
SomeClass someotherobject;
memcpy(&someotherobject, temporary_storage, sizeof(SomeClass));

at this point 'someobject' and 'someotherobject' hold the same value.
So in strict terms it looks like that only if we copy the bytes back, we
get the same object, and making an object in our bytes is not guaranteed
to work.
While the Standard does appear to be limiting to copying /back/, the
intention is to probably provide a way to copy POD objects using char
or unsigned char arrays as the medium. I bet you can learn more on the
rationale and the particulars of the use of "the" in the aforementioned
paragraph of the Standard in comp.std.c++ :-)
The only examples I have seen in TC++PL3 for placement new, are in the
style:
int x;

int *p= new(&x) int;


Examples are what they are, examples. It doesn't necessarily mean you
cannot use placement new with non-POD objects or for "copying".

V
Jul 23 '05 #19

P: n/a
Victor Bazarov wrote:
Examples are what they are, examples. It doesn't necessarily mean you
cannot use placement new with non-POD objects or for "copying".

Is this also guaranteed to work? SomeClass is a non-POD type here:
#include <iostream>
#include <new>

class SomeClass
{
public:
SomeClass() { std::cout<<"Constructor called!\n"; }
~SomeClass() { std::cout<<"Destructor called!\n"; }

void somefunc() const { std::cout<<"somefunc() called!\n"; }
};
int main()
{
using namespace std;

unsigned char *parray= new unsigned char[sizeof(SomeClass)];

SomeClass *pSomeClass= new(parray) SomeClass;

pSomeClass->somefunc();

pSomeClass->~SomeClass();

delete[] parray;
}


--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #20

P: n/a
Ioannis Vranos wrote:
Victor Bazarov wrote:
Examples are what they are, examples. It doesn't necessarily mean you
cannot use placement new with non-POD objects or for "copying".


Is this also guaranteed to work? SomeClass is a non-POD type here:
#include <iostream>
#include <new>

class SomeClass
{
public:
SomeClass() { std::cout<<"Constructor called!\n"; }
~SomeClass() { std::cout<<"Destructor called!\n"; }

void somefunc() const { std::cout<<"somefunc() called!\n"; }
};
int main()
{
using namespace std;

unsigned char *parray= new unsigned char[sizeof(SomeClass)];

SomeClass *pSomeClass= new(parray) SomeClass;

pSomeClass->somefunc();

pSomeClass->~SomeClass();

delete[] parray;
}

Of course it is! What could possibly make you think that it isn't?

V
Jul 23 '05 #21

P: n/a
REH

"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in message
news:1112129815.839667@athnrd02...
Victor Bazarov wrote:
Examples are what they are, examples. It doesn't necessarily mean you
cannot use placement new with non-POD objects or for "copying".

Is this also guaranteed to work? SomeClass is a non-POD type here:
#include <iostream>
#include <new>

class SomeClass
{
public:
SomeClass() { std::cout<<"Constructor called!\n"; }
~SomeClass() { std::cout<<"Destructor called!\n"; }

void somefunc() const { std::cout<<"somefunc() called!\n"; }
};
int main()
{
using namespace std;

unsigned char *parray= new unsigned char[sizeof(SomeClass)];

SomeClass *pSomeClass= new(parray) SomeClass;

pSomeClass->somefunc();

pSomeClass->~SomeClass();

delete[] parray;
}


--
Ioannis Vranos


It's fine except you are calling the constructor twice.

REH
Jul 23 '05 #22

P: n/a
REH

"REH" <bo***@nowhere.net> wrote in message
news:d2*********@cui1.lmms.lmco.com...

"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in message
news:1112129815.839667@athnrd02...
int main()
{
using namespace std;

unsigned char *parray= new unsigned char[sizeof(SomeClass)];

SomeClass *pSomeClass= new(parray) SomeClass;

pSomeClass->somefunc();

pSomeClass->~SomeClass();

delete[] parray;
}


--
Ioannis Vranos


It's fine except you are calling the constructor twice.

REH

Sorry, my bad. I misread "somefunc" as "SomeClass."


Jul 23 '05 #23

P: n/a
REH wrote:
"REH" <bo***@nowhere.net> wrote in message
news:d2*********@cui1.lmms.lmco.com...
"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in message
news:1112129815.839667@athnrd02...

pSomeClass->somefunc();

--
Ioannis Vranos


It's fine except you are calling the constructor twice.

REH


Sorry, my bad. I misread "somefunc" as "SomeClass."


Besides, there is no way to call a constructor, so it wouldn't compile
if it were written as pSomeClass->SomeClass();

V
Jul 23 '05 #24

P: n/a
Victor Bazarov wrote:
Is this also guaranteed to work? SomeClass is a non-POD type here:
#include <iostream>
#include <new>

class SomeClass
{
public:
SomeClass() { std::cout<<"Constructor called!\n"; }
~SomeClass() { std::cout<<"Destructor called!\n"; }

void somefunc() const { std::cout<<"somefunc() called!\n"; }
};
int main()
{
using namespace std;

unsigned char *parray= new unsigned char[sizeof(SomeClass)];

SomeClass *pSomeClass= new(parray) SomeClass;

pSomeClass->somefunc();

pSomeClass->~SomeClass();

delete[] parray;
}


Of course it is! What could possibly make you think that it isn't?

I asked because the standard says that we can *only* read non-POD types as unsigned chars
(more accurately, the memcpy() back and forth retaining the original value is guaranteed
only for POD types).


--
Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 23 '05 #25

P: n/a
Ioannis Vranos wrote:
Victor Bazarov wrote:
Is this also guaranteed to work? SomeClass is a non-POD type here:
#include <iostream>
#include <new>

class SomeClass
{
public:
SomeClass() { std::cout<<"Constructor called!\n"; }
~SomeClass() { std::cout<<"Destructor called!\n"; }

void somefunc() const { std::cout<<"somefunc() called!\n"; }
};
int main()
{
using namespace std;

unsigned char *parray= new unsigned char[sizeof(SomeClass)];

SomeClass *pSomeClass= new(parray) SomeClass;

pSomeClass->somefunc();

pSomeClass->~SomeClass();

delete[] parray;
}



Of course it is! What could possibly make you think that it isn't?


I asked because the standard says that we can *only* read non-POD types
as unsigned chars (more accurately, the memcpy() back and forth
retaining the original value is guaranteed only for POD types).


The difference about just reading the bytes into the memory of the object
and placement new is that placement new assures _construction_ whereas the
POD doesn't have any constructors to execute. You may of course construct
a POD object using placement new, but the standard allows you to do away
with it, but only for PODs.

V
Jul 23 '05 #26

This discussion thread is closed

Replies have been disabled for this discussion.