Placement new and explicit destruction

R

REH

This curiosity popped into my head on the way to work today. I
wouldn't actually do this, but just wondering. Is the following
defined behavior?

#include <new>

class T { };

int main()
{
T* p = new T();

p->~T();
new(p) T();

delete p;

return 0;
}
 
V

Victor Bazarov

REH said:
This curiosity popped into my head on the way to work today. I
wouldn't actually do this, but just wondering. Is the following
defined behavior?

#include <new>

class T { };

int main()
{
T* p = new T();

p->~T();
new(p) T();

delete p;

return 0;
}

Yes. It's the pattern some folks are using to "forward constructor
calls". The functionality is so often asked for that the Committee
is changing the language to allow forwarding constructors, BTW.

V
 
R

REH

Yes. It's the pattern some folks are using to "forward constructor
calls". The functionality is so often asked for that the Committee
is changing the language to allow forwarding constructors, BTW.

Thanks for replying Victor. I'm not familiar with the term "forward
constructor" and Google is no help. Could you please point me to some
information (or even give a quick explanation)?

Rich
 
V

Victor Bazarov

REH said:
Thanks for replying Victor. I'm not familiar with the term "forward
constructor" and Google is no help. Could you please point me to some
information (or even give a quick explanation)?

Given the class

class A {
double d;
public:
A(double a) : d(a) { /* and something else important */}
A(double const *pa, size_t i) : d(pa) { /* again */ }
};

, had there been constructor forwarding, we could just do

...
A(double const *pa, index i) : A(pa) {}

and it would call the former constructor (with a single 'double'
argument).

V
 
J

James Kanze

Yes. It's the pattern some folks are using to "forward constructor
calls". The functionality is so often asked for that the Committee
is changing the language to allow forwarding constructors, BTW.

It's definitly legal, but I don't quite see what it has to do
with forwarding constructors. If I've understood the proposals
correctly, a forwarding constructor is where one constructor
first calls another constructor to do the job, then does some
additional processing. Here, the poster first allocates and
constructs the object, then destructs it without deallocating
(leaving raw memory), then reconstructs it in the raw memory.
 
R

REH

It's definitly legal, but I don't quite see what it has to do
with forwarding constructors. If I've understood the proposals
correctly, a forwarding constructor is where one constructor
first calls another constructor to do the job, then does some
additional processing. Here, the poster first allocates and
constructs the object, then destructs it without deallocating
(leaving raw memory), then reconstructs it in the raw memory.

I don't want to speak for Victor, but what I think he was saying was
that placement new can be used to simulate one constructor calling
another. Thus:

class foo {
public:

foo(int i);

foo(double d);
};

foo::foo(double d)
{
new(this) foo(123);
}
 
V

Victor Bazarov

REH said:
I don't want to speak for Victor, but what I think he was saying was
that placement new can be used to simulate one constructor calling
another. Thus:

class foo {
public:

foo(int i);

foo(double d);
};

foo::foo(double d)
{
new(this) foo(123);
}

You got it. I of course don't mean that the object should be
constructed twice, so the latter c-tor needs to have the destruction
in it too:

foo::foo(double d)
{
this->~foo();
new (this) foo(123);
}

V
 
J

James Kanze

I don't want to speak for Victor, but what I think he was saying was
that placement new can be used to simulate one constructor calling
another.

Except that it can't, in general.
class foo {
public:
foo(int i);
foo(double d);
};
foo::foo(double d)
{
new(this) foo(123);

Which is undefined behavior if the class has a non-trivial
destructor.

The reason why the standards committee is adding forwarding
constructors is precisely because there is no way of simulating
it in the current language.
 
J

James Kanze

[...]
You got it. I of course don't mean that the object should be
constructed twice, so the latter c-tor needs to have the destruction
in it too:
foo::foo(double d)
{
this->~foo();
new (this) foo(123);
}

That's technically also undefined behavior, since you are
calling the destructor on an object whose constructor hasn't yet
finished running. (In practice, of course, you know what's in
your class, and you'll have ensured that you've set up enough
for the destructor to run without problems before calling it.)
 

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