繁体   English   中英

将新的展示位置用作副本分配运算符是否不好?

[英]Is using a placement new as a copy assignment operator bad?

有时我想使用const成员来制作类/结构。 我意识到这是一个坏主意,有多种原因,但是为了争辩,让我们假装唯一的原因是,至少可以说,它使格式正确的operator =麻烦。 但是,我构造了一个相当简单的解决方法,如以下结构所示:

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;
  }

};

忽略析构函数并移动语义,有什么真正的大理由为什么不应该这样做? 在我看来,它更像是类型安全的

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

因此,问题的摘要是:是否有任何主要理由不应该将placement-new用于实现与副本构造具有相同语义的副本分配?

我认为这里的placement new不是问题,但是const_cast会产生未定义的行为:

C ++ 10.1.7.1-4除了可以声明任何声明为可变的类成员(10.1.1)之外,任何在其生存期内(6.6.3)修改const对象的尝试都会导致未定义的行为。

在编译器开始优化之前,您可能会避免这样做。

另一个问题是在由活动(未破坏)对象占用的内存中使用新的放置方式。 但是,当有问题的对象具有微不足道的析构函数时,您可能会摆脱这种情况。

有什么真正的大理由为什么不应该这样做?

  1. 您必须绝对确保每个派生类都定义自己的赋值运算符,即使它是微不足道的。 因为派生类隐式定义的副本分配运算符会将所有内容搞混。 它将调用S::operator= ,它将在其位置重新创建错误的对象类型

  2. 这样的销毁构造赋值运算符不能被任何派生类重用 因此,不仅要强迫派生类提供一个显式的复制运算符,而且要迫使它们在其赋值运算符中遵循相同的销毁和构造习惯。

  3. 您必须绝对确保在这样的赋值运算符破坏和构造对象时,没有其他线程可以访问该对象

  4. 一个类可能包含一些数据成员,这些成员不能受到赋值运算符的影响 例如,一个线程安全的类可能具有某种互斥量或关键部分成员,当当前线程将要破坏并构造该互斥量时,其他一些线程将在其上等待...

  5. 在性能方面,它几乎没有标准的复制和交换习惯的优势。 那么,克服上述所有痛苦将有何收获?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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