Reputation: 1945
So I was going through a piece of text in C++ and came across the following piece of code:
class example
{
int dataMember;
public:
example& assign(const example& source)
{
if(this!=&source)
{
this->~example();
new (this) example(source);
}
}
};
Okay so I am trying to decode what this function assign is doing. What I have understood yet:
The function takes a constant reference of instance of the class and returns a reference to the class.
Inside the if
block, firstly the destructor is called for the current instance (As far as I know, current object is destroyed and memory is freed).
Now the main question:
new (this) example(source)
This line is troubling me. What is happening here?
If I am asked to guess, I would say that a new object is being created and is assigned as the current object, as I can infer from this
keyword.
Can anyone clear this up? How exactly are things going on here?
Is this kind of method safe? (If allocation is happening dynamically, programmer will have to deallocate it in future manually)
Thanks.
Upvotes: 3
Views: 202
Reputation: 11116
What you are seeing is an attempt at code-reusage. The idea is to use the copy constructor to implement the assignment operator (or, in this case an assignment function).
First, to get rid of the easy stuff:
The if
ensures that a self assignment (e.g. x.assign(x)
) is being handled correctly. This is necessary since the implementation relies on the fact that changing *this
does not change source
. By comparing this
to the address of the other object, this does test the objects for equality, but for sameness.
The function is missing a return *this;
, but you probably noticed that already.
Now to the two remaining lines:
this->~example();
Explicitly calls the destructor of the class example
. After that line the this
pointer no longer points to an object, but to uninitialized memory of sizeof(example)
.
new (this) example(source);
Is the so-called placement new, which does not allocate memory, but simply creates a new example
at the location pointed to by this
by calling its copy constructor. In a way this is the syntax to explicitly call a constructor w/o allocating any memory.
Note that this reuses the memory that *this
held previously, no matter where that is: It could even be e.g. a virtual
base of an element of a dynamically allocated array...
As to the safety: In practice this is safe (although ugly and possibly not very efficient) as long as neither the constructor nor destructor throw. However, you can run into problems when deriving from a class that attempts to be sneaky like that.
If you want to know the simplest way to write an assignment operator/function that reuses the copy constructor, check this question, which basically boils down to:
example& assign(example source)
{
swap(*this, source);
return *this;
}
The most important differences:
swap
are exception safe (which they should always be).Upvotes: 3
Reputation: 17415
This part destroys the object:
this->~example();
It doesn't release the memory though, except for memory that is released due to the destructor call. Then, it proceeds with an invocation of "placement new":
new (this) example(source);
This will construct an object on the (unreleased) memory of the former object.
Concerning the safety of this, it is at least dangerous. If after destroying the object you fail to create the new object, you have a weird zombie object that will get destroyed a second time (causing undefined behaviour) when its normal lifetime ends.
Upvotes: 1