473,382 Members | 1,353 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,382 software developers and data experts.

using placement new to re-initialize part of an object

Hi. I'm using placement new to re-initialize part of an object. Is
this OK?

struct BaseImp
{
All& r_all;
BaseImp(All& all) : r_all(all)
};

struct Calc::Imp : public BaseImp
{
int d_x;
Imp(All& all, int x) : BaseImp(all), d_x(x) { }
}

void Calc::somefunction(All& newall)
{
assert(typeid(*d_imp) == typeid(Imp));
new (d_imp) BaseImp(newall);
}

This way, d_imp->d_x is unchanged, but d_imp->r_all is changed.

What does the standard say about this?

Thanks.

Apr 4 '06 #1
5 2902
re**************@yahoo.com wrote:

Hi. I'm using placement new to re-initialize part of an object. Is
this OK?
No, at least not the way you're doing it.

Also, next time please post compilable code. Remember, what we do is
cut and paste your code and then try to compile it. The numerous
syntax errors are a distraction from your question.

Add:

#include <cassert>
#include <typeinfo>
class All; // ???

struct BaseImp
{
All& r_all;
BaseImp(All& all) : r_all(all)
You omitted:

{}
};

struct Calc::Imp : public BaseImp
What is Calc? Is it a class that has Imp as a subclass? Or is it a
namespace? If the latter, you can't define Imp this way - you must do
so as:

namespace Calc {
struct Imp : public BaseImp

etc.
{
int d_x;
Imp(All& all, int x) : BaseImp(all), d_x(x) { }
}
You omitted the semicolon after the closing brace.

void Calc::somefunction(All& newall)
{
assert(typeid(*d_imp) == typeid(Imp));
What the heck is d_imp?
new (d_imp) BaseImp(newall);
}
I've probably missed several more errors.

This way, d_imp->d_x is unchanged, but d_imp->r_all is changed.
What makes you think that d_x is unchanged?

What does the standard say about this?


This goes by the technical term of "a hack." It causes undefined
behavior, because an existing object never has its destructor called,
but you are then reusing the memory where that undestructed object
sits. Moreover, it looks like you now intend to use the object as an
Impl, even though you just created a BaseImp. That too would be
undefined behavior.

There are much better, less-hackish ways of doing this, but if you
insist on using placement new, you're going to at least have to call
the destructor of the object before calling placement new, and then
you're going to have to use the object you then create, not a different
object.

Wait a second - this is a joke, right? Okay, you got me. The problem
is that people on this newsgroups really do post code like this, so
it's hard to tell when they're kidding.

Best regards,

Tom

Apr 4 '06 #2
Thomas Tutone wrote:
re**************@yahoo.com wrote:

Hi. I'm using placement new to re-initialize part of an object. Is
this OK?
No, at least not the way you're doing it.

Also, next time please post compilable code. Remember, what we do is
cut and paste your code and then try to compile it. The numerous
syntax errors are a distraction from your question.

Add:

#include <cassert>
#include <typeinfo>
class All; // ???

struct BaseImp
{
All& r_all;
BaseImp(All& all) : r_all(all)


You omitted:

{}
};

struct Calc::Imp : public BaseImp


What is Calc? Is it a class that has Imp as a subclass? Or is it a
namespace? If the latter, you can't define Imp this way - you must do
so as:

namespace Calc {
struct Imp : public BaseImp

etc.
{
int d_x;
Imp(All& all, int x) : BaseImp(all), d_x(x) { }
}


You omitted the semicolon after the closing brace.

void Calc::somefunction(All& newall)
{
assert(typeid(*d_imp) == typeid(Imp));


What the heck is d_imp?
new (d_imp) BaseImp(newall);
}


I've probably missed several more errors.

This way, d_imp->d_x is unchanged, but d_imp->r_all is changed.


What makes you think that d_x is unchanged?

What does the standard say about this?


This goes by the technical term of "a hack." It causes undefined
behavior, because an existing object never has its destructor called,
but you are then reusing the memory where that undestructed object
sits.


Where do you find that this is undefined behavior? From the standard:

[3.8/4] A program may end the lifetime of any object by reusing the
storage which the object occupies or by explicitly calling the destructor
for an object of a class type with a non-trivial destructor. For an object
of a class type with a non-trivial destructor, the program is not required
to call the destructor explicitly before the storage which the object
occupies is reused or released; however, if there is no explicit call to
the destructor or if a delete-expression (5.3.5) is not used to release
the storage, the destructor shall not be implicitly called and any program
that depends on the side effects produced by the destructor has undefined
behavior.

The way I read this says: you can reuse the memory that an object occupies
without calling its destructor, provided you are not relying on side
effects of a possibly non-trivial destructor in the program.

Moreover, it looks like you now intend to use the object as an
Impl, even though you just created a BaseImp. That too would be
undefined behavior.
This maybe true. I am not sure though. The way I see it, the OP reuses the
memory occupied by a BaseImp subobject inside an Impl object and constructs
a new BaseImp object in there. It is quite possible that this invalidates
the ambient Impl object, but I don't know what the standard says about
this. Do you happen to know a reference?

There are much better, less-hackish ways of doing this,
Agreed.
but if you
insist on using placement new, you're going to at least have to call
the destructor of the object before calling placement new, and then
you're going to have to use the object you then create, not a different
object.
I agree, that would be safer.
Wait a second - this is a joke, right? Okay, you got me. The problem
is that people on this newsgroups really do post code like this, so
it's hard to tell when they're kidding.


I, too, hope it's a joke.
Best

Kai-Uwe Bux
Apr 5 '06 #3

Kai-Uwe Bux wrote:

You raise good points. Let me respond as best I can.
This goes by the technical term of "a hack." It causes undefined
behavior, because an existing object never has its destructor called,
but you are then reusing the memory where that undestructed object
sits.


Where do you find that this is undefined behavior? From the standard:

[3.8/4] A program may end the lifetime of any object by reusing the
storage which the object occupies or by explicitly calling the destructor
for an object of a class type with a non-trivial destructor. For an object
of a class type with a non-trivial destructor, the program is not required
to call the destructor explicitly before the storage which the object
occupies is reused or released; however, if there is no explicit call to
the destructor or if a delete-expression (5.3.5) is not used to release
the storage, the destructor shall not be implicitly called and any program
that depends on the side effects produced by the destructor has undefined
behavior.

The way I read this says: you can reuse the memory that an object occupies
without calling its destructor, provided you are not relying on side
effects of a possibly non-trivial destructor in the program.


This just may be an example of my saying the glass is half-empty, and
you saying the glass is half full. The section you quote says, in
effect, if an object has a non-trivial destructor, then the failure to
call the destructor is undefined unless there is nothing that relies,
expressly or implicitly, on the behavior of that destructor. To me,
that means undefined behavior. You say, quite reasonably, that so long
as an object has a trivial destructor, or at least there is nothing
relying on the behavior of the structure, doing this is well defined.
To me, those constraints are too great - they are enough for me to say,
"because using this idiom will often result in undefined behavior, one
should not use this idiom." Among other things, I would think that the
compiler may make certain aliasing assumptions when it optimizes that
will turn out not to be true.

Moreover, it looks like you now intend to use the object as an
Impl, even though you just created a BaseImp. That too would be
undefined behavior.


This maybe true. I am not sure though. The way I see it, the OP reuses the
memory occupied by a BaseImp subobject inside an Impl object and constructs
a new BaseImp object in there. It is quite possible that this invalidates
the ambient Impl object, but I don't know what the standard says about
this. Do you happen to know a reference?


No offhand. But consider: the compiler may add padding to BaseImp and
may not add that same padding to to Impl. The compiler could
conceivably overwrite that padding. But perhaps I am wrong about this.
But in any case, here's an analogy - the OP is creating the moral
equivalent of the following:

union { BaseImpl base; Impl impl };

Doing that is generally undefined except for POD. (Perhaps I am
overstating that a bit, but you know what I mean). At the very least,
it illustrates that this is a hack.

Best regards,

Tom

Apr 5 '06 #4
>This maybe true. I am not sure though. The way I see it, the OP reuses the
memory occupied by a BaseImp subobject inside an Impl object and constructs
a new BaseImp object in there. It is quite possible that this invalidates
the ambient Impl object, but I don't know what the standard says about
this. Do you happen to know a reference?


What do you mean by "the ambient Impl object"?

There are much better, less-hackish ways of doing this,


Such as? Using pointers?
Thomas, sorry for not posting compilable code. I just wanted to get
the point across, not intending for anyone to compile code. But here
is compilable code.

struct B
{
int& r_b;
B(int& b) : r_b(b) { }
};

struct D : public B
{
int d_d;
D(int& b, int d) : B(b), d_d(d) { }
};

int main()
{
int x=1, y=2;
D * d = new D(x,1);
new (d) B(y);
}

This is a way of re-assigning a reference. The reason for doing this
that I'm implementing a swap function (it's not a joke), and I'd like
to reset a reference. Constructing a brand new D object is expensive.

I suppose one should call the destructor to be correct prioir to
calling placement new

D * d = new D(x,1);
d->B::~B();
new (d) B(y);

But before one does this one should make sure that the destructor of B
is not virtual.

In any case, in .Net 2003, when debugging, and I'm on "new D(x, 1)"
line, when I step over (with F10), the debugger skips the "d->B::~B()"
call. This means there was no code generated for the destructor call.
Of course, this issue is specific to MSVC, but I suspect all compilers
would behave the same way.

Apr 5 '06 #5
re**************@yahoo.com wrote:

There are much better, less-hackish ways of doing this,

Such as? Using pointers?


Based on what you want to do, yes. Possibly smart pointers rather than
raw pointers. Or perhaps you could create a small "reseatable
reference" class that uses a pointer internally, but has a
reference-like interface.
Thomas, sorry for not posting compilable code. I just wanted to get
the point across, not intending for anyone to compile code. But here
is compilable code.

struct B
{
int& r_b;
B(int& b) : r_b(b) { }
};

struct D : public B
{
int d_d;
D(int& b, int d) : B(b), d_d(d) { }
};

int main()
{
int x=1, y=2;
D * d = new D(x,1);
new (d) B(y);
}
Thanks.

This is a way of re-assigning a reference. The reason for doing this
that I'm implementing a swap function (it's not a joke), and I'd like
to reset a reference. Constructing a brand new D object is expensive.

I suppose one should call the destructor to be correct prioir to
calling placement new

D * d = new D(x,1);
d->B::~B();
new (d) B(y);

But before one does this one should make sure that the destructor of B
is not virtual.

In any case, in .Net 2003, when debugging, and I'm on "new D(x, 1)"
line, when I step over (with F10), the debugger skips the "d->B::~B()"
call. This means there was no code generated for the destructor call.
Of course, this issue is specific to MSVC, but I suspect all compilers
would behave the same way.


I suspect you're right. As Kai-Uwe Bux pointed out, the behavior _may_
be well defined if the class has a trivial destructor. A class that
contains nothing but POD and a reference presumably has a trivial
destructor that essentially is a no-op.

But I do think you're better off using pointers, and thereby make your
class objects assignable, rather than trying to subvert the rule that
references can't be reseated.

Best regards,

Tom

Apr 5 '06 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Wenjie | last post by:
Hello, I read that the placement new looks like: void* SomeClass::operator new(size_t, void* location) { return location; } If for some reason, I overload the operator new as:
23
by: Giancarlo Niccolai | last post by:
Hello all. I have peeked through the FAQ and all relevant links, and also through Stroustrup book, but I have not been able to find an answer, so I have to post here as a last resort. It...
20
by: Ioannis Vranos | last post by:
When we use the standard placement new operator provided in <new>, and not a definition of owr own, isn't a call to placement delete enough? Consider the code: #include <new>
5
by: REH | last post by:
Hi. I want to have a union that contained various types, some of which are classes with constructors. I'm attempting to acheive this with placement new. Please tell me if the following code...
6
by: Marc Mutz | last post by:
Hi, I'm in discussion with a lib vendor who uses placement new to forward construction to another ctor, like this: MyClass( ... ) { new (this) MyClass( ... ); } I asked them to use a private...
3
by: Brian Gideon | last post by:
I stumbled across something odd today about the placement of the using keyword. Section 9.3.2 of the C# v1.1 specification did not answer my question. My confusion is isolated to what happens in...
1
by: Raed Sawalha | last post by:
i have the following scenario I've created MFC Application using Visual Studio 2003, then change the project settings to use Managed Extensions as follows: 1. Configuration...
4
by: sreedhar.cs | last post by:
Hi all, In my application,I want to place a vector in a specific location in shared memory.(a user supplied pointer). I understand that the STL allocator mechanism places the data objects within...
15
by: mangesh | last post by:
This code is from c++ faq in section 11 : void someCode() { char memory; void* p = memory; Fred* f = new(p) Fred(); f->~Fred(); // Explicitly call the destructor for the placed object }
5
by: Lagarde Sébastien | last post by:
Hello, I write code to debug new call with following macro: #define new (MemoryManager::Get().setOwner (__FILE__, __LINE__, _FUNCTION-), FALSE) ? NULL : new The setOwner allow to save the...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.