[英]Use of placement-new operator and copy constructor instead of assignment operator
[英]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对象的尝试都会导致未定义的行为。
在编译器开始优化之前,您可能会避免这样做。
另一个问题是在由活动(未破坏)对象占用的内存中使用新的放置方式。 但是,当有问题的对象具有微不足道的析构函数时,您可能会摆脱这种情况。
有什么真正的大理由为什么不应该这样做?
您必须绝对确保每个派生类都定义自己的赋值运算符,即使它是微不足道的。 因为派生类的隐式定义的副本分配运算符会将所有内容搞混。 它将调用S::operator=
,它将在其位置重新创建错误的对象类型 。
这样的销毁构造赋值运算符不能被任何派生类重用 。 因此,不仅要强迫派生类提供一个显式的复制运算符,而且要迫使它们在其赋值运算符中遵循相同的销毁和构造习惯。
您必须绝对确保在这样的赋值运算符破坏和构造对象时,没有其他线程可以访问该对象 。
一个类可能包含一些数据成员,这些成员不能受到赋值运算符的影响 。 例如,一个线程安全的类可能具有某种互斥量或关键部分成员,当当前线程将要破坏并构造该互斥量时,其他一些线程将在其上等待...
在性能方面,它几乎没有标准的复制和交换习惯的优势。 那么,克服上述所有痛苦将有何收获?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.