关于c ++:我可以在operator =中使用placement new(this)吗?

Can I use placement new(this) in operator=?

背景:我有一个包含许多变量的复杂类。我有一个健全的和经过测试的复制建设者:

1
2
3
4
5
Applepie::Applepie( const Applepie &copy) :
m_crust(copy.m_crust),
m_filling(copy.m_filling)
{
}

在初始化器列表中调用的一些成员变量copy构造函数执行分配。

问题:我需要创建operator=。我可以简单地执行以下操作,而不是使用赋值而不是初始化列表来复制现有的构造,以及释放正在被替换的内存等等:

1
2
3
4
5
6
7
8
9
Applepie& Applepie::operator=( const Applepie &copy)
{
    if( this != &copy)
    {
       this->~Applepie(); // release own object
       new(this) Applepie(copy); // placement new copy constructor
    }
    return *this;
}

换句话说,destroy self后面跟着placement new copy构造函数在语义上与operator=相同吗?

这似乎有可能显著减少重复代码,并确认每个变量都已正确初始化,但在分配过程中可能会稍微降低效率。我是不是错过了一些更难懂的东西?

理论基础:我的实际班级大约有30个变量。我担心的是,我的复制构造函数和赋值运算符都必须复制全部30个,并且代码可能会出现分歧,导致这两个操作执行的方式不同。


正如萨特在"例外C++"中所说的,它也不例外。这意味着,如果在new或新对象的构造过程中发生任何错误,则赋值的左手操作数处于错误(未定义)状态,这将导致更多的麻烦。我强烈建议使用copy&swap习惯用法。

1
2
3
4
5
6
Applepie& Applepie::operator=(Applepie copy)
{
  swap(m_crust, copy.m_crust);
  swap(m_filling, copy.m_filling);
  return *this;
}

当您的对象也使用PIMPL习惯用法(指向实现的指针)时,交换只通过更改两个指针来完成。


除了Rene的答案之外,还有一个问题,即如果applepie是实际对象的基类,会发生什么情况:applepie将用错误类型的对象替换对象!