简体   繁体   中英

Is using a placement new as a copy assignment operator bad?

Sometimes I want to make classes/structs with const members. I realize that this is a bad idea for multiple reasons, but for the sake of argument let's pretend the only reason is that it makes a well-formed operator = a hassle, to say the least. However, I contrived a fairly simple work-around to it, as demonstrated by this struct:

struct S {

  const int i;

  S(int i) : i(i) {}

  S(const S& other) : i(other.i) {}

  S& operator =(const S& other) {
    new (this) S(other);
    return *this;
  }

};

Ignoring destructors and move semantics, is there any really big reason why this shouldn't be done? It seems to me like a more type-safe version of

S& operator =(const S& other) {
  const_cast<int&>(i) = other.i;
  return *this;
}

So, the summary of the question is this: is there any major reason placement-new should not be used to implement copy assignment to have the same semantics as a copy construction?

I don't believe that placement new is a problem here but the const_cast which produces undefined behavior:

C++ 10.1.7.1-4 Except that any class member declared mutable (10.1.1) can be modified, any attempt to modify a const object during its lifetime (6.6.3) results in undefined behavior.

You'll probably get away with this until compiler starts to optimize things.

The other problem is the use of a placement new on a piece memory occupied by living (non-destroyed) object. But you'll probably get away with this while object in question has a trivial destructor.

is there any really big reason why this shouldn't be done?

  1. You must be absolutely sure that every derived class defines its own assignment operator, even if it is trivial. Because an implicitly defined copy-assignment operator of a derived class will screw everything. It'll call S::operator= which will re-create a wrong type of object in its place.

  2. Such destroy-and-construct assignment operator can't be re-used by any derived class . So, not only you are forcing derived classes to provide an explicit copy operator, but you're forcing them to stick to the same destroy-and-construct idiom in their assignment operator.

  3. You must be absolutely sure that no other thread is accessing the object while it is being destroyed-and-constructed by such assignment operator.

  4. A class may have some data members that must not be affected by the assignment operator . For example, a thread-safe class may have some kind of mutex or critical section member, with some other thread waiting on them right when the current thread is going to destroy-and-construct that mutex...

  5. Performance-wise, it has virtually no advantage over standard copy-and-swap idiom. So what would be the gain in going through all the pain mentioned above?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM