using placement new to forward ctor calls

M

Marc Mutz

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 init() function instead, but
they claim:
you might be correct that using placement new to forward
construction is not well defined in the general case. In
our case however it is, as the class only contains one
pimpl-pointer (no members that have a constructor
and no vtable). In this case it's perfectly valid to use
the construct we're using.

Please supply me with ammonition to make them reconsider
(or tell me they're right :/).

Thanks,
Marc
 
A

Alf P. Steinbach

* Marc Mutz:
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 init() function instead, but
they claim:

Please supply me with ammonition to make them reconsider
(or tell me they're right :/).

"Right" or "wrong" is not really relevant wrt. a platform-specific library.
Either it works, or not. The technical problem is whether it works with all
relevant compilers (it may, or it may not), and with future versions of
those compilers (it may not). The problem for a client is that the
construct above is _unnecessary_ UB, and bodes not well for the quality of
the rest of the library implementation. It indicates that they're "clever"
technicians, not engineers; an engineer wouldn't do a thing like that.
 
J

Jonathan Mcdougall

Marc said:
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 init() function instead, but
they claim:

Please supply me with ammonition to make them reconsider
(or tell me they're right :/).

1) It's not easy to understand, it's not clear what this code is trying
to achieve
2) It's not common practice
3) It's brittle, it may break on another system/compiler/version.
4) It may be wrong (is this really a MyClass?)
5) It may be less "efficient" than calling an init() function
6) It is illegal
7) The fact that they admit "using placement new to forward
construction is not well defined in the general case" is quite scary.

And 8) change the library.


Jonathan
 
L

leonardo77

The only thing I have to add to the superior answers you have received
so far is that I am not accustomed to being born twice in spite of
dying once. And it's UB,thus you can expect demons, aliens, formatted
drives and absense of errors.
 
P

Pete Becker

leonardo77 said:
And it's UB,thus you can expect demons, aliens, formatted
drives and absense of errors.

Where in the standard is that requirement? <g> In fact, I expect that it
does exactly what it was described as doing. With suitable knowledge of
the target platform and of the compiler and with appropriate testing
there's no need to fear code whose behavior isn't defined by the
language definition.
 
M

Mercator

Marc said:
I'm in discussion with a lib vendor who uses placement new
to forward construction to another ctor, like this:
MyClass( ... ) {
new (this) MyClass( ... );
}
Please supply me with ammonition to make them reconsider
(or tell me they're right :/).

It's uncool. It looks as if they dont know what they are doing.
 
M

Me

Marc said:
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 init() function instead, but
they claim:

Please supply me with ammonition to make them reconsider
(or tell me they're right :/).

This is already in shaky grounds because the lifetime of a non-POD
before construction completes and before destruction begins is really
hard to reason about and there are lots of restrictions on what is well
defined and what isn't (see 3.8 and the sections it references for more
details). But if we ignore that and pick a simpler reason why this code
is illegal:

3.8/1 "The lifetime of an object of type T begins when ... if T is a
class type and the constructor invoked to create the object is
non-trivial (12.1), the constructor call has completed."

MyClass::MyClass(...)
{
new ((void*)this) MyClass(...); //1
} //2

So what happens here is that they are using placement new to create a
new object at the location pointed to by this //1. This creates a new
MyClass object, that's fine (totally ignoring the issues I talked about
above). The problem occurs when the MyClass ctor returns //2, the
constructor call has completed, which means *two* MyClass objects are
created at the same memory location, which is illegal since MyClass is
not a POD struct. Since there is no way to forward ctor calls in the
current standard, the only legal thing to do is call an init()
function.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top