Thomas Tutone wrote:
[color=blue]
>
removeps-generic@yahoo.com wrote:
>
>[color=green]
>> Hi. I'm using placement new to re-initialize part of an object. Is
>> this OK?[/color]
>
> 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; // ???
>[color=green]
>>
>> struct BaseImp
>> {
>> All& r_all;
>> BaseImp(All& all) : r_all(all)[/color]
>
> You omitted:
>
> {}
>[color=green]
>> };
>>
>> struct Calc::Imp : public BaseImp[/color]
>
> 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.
>[color=green]
>> {
>> int d_x;
>> Imp(All& all, int x) : BaseImp(all), d_x(x) { }
>> }[/color]
>
> You omitted the semicolon after the closing brace.
>[color=green]
>>
>> void Calc::somefunction(All& newall)
>> {
>> assert(typeid(*d_imp) == typeid(Imp));[/color]
>
> What the heck is d_imp?
>[color=green]
>> new (d_imp) BaseImp(newall);
>> }[/color]
>
> I've probably missed several more errors.
>[color=green]
>>
>> This way, d_imp->d_x is unchanged, but d_imp->r_all is changed.[/color]
>
> What makes you think that d_x is unchanged?
>
>[color=green]
>> What does the standard say about this?[/color]
>
> 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.[/color]
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.
[color=blue]
> 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.[/color]
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?
[color=blue]
> There are much better, less-hackish ways of doing this,[/color]
Agreed.
[color=blue]
> 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.[/color]
I agree, that would be safer.
[color=blue]
> 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.[/color]
I, too, hope it's a joke.
Best
Kai-Uwe Bux