我可以在operator =中使用placement new(this)吗?

时间:2011-08-24 15:15:07

标签: c++ operator-overloading placement-new

背景 我有一个复杂的类,有很多变量。我有一个声音和测试的复制构造函数:

Applepie::Applepie( const Applepie &copy) :
m_crust(copy.m_crust),
m_filling(copy.m_filling)
{
}

在inativeizer列表中调用的一些成员变量复制构造函数执行分配。

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

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后跟一个放置新的复制构造函数在语义上与operator =?

相同

这似乎有可能大大减少重复代码并确认每个变量都已正确初始化,但代价是在分配期间可能会略微降低效率。我错过了一些比较模糊的东西吗?

理由: 我的实际班级有大约30个变量。我担心我的复制构造函数和我的赋值操作符都必须复制所有三十个,并且代码可能会发散,导致两个操作以不同的方式执行操作。

2 个答案:

答案 0 :(得分:6)

正如“Exceptional C ++”中的Herb Sutter所说,它并非例外。这意味着,如果在new或构造新对象期间出现任何问题,则赋值的左手操作数处于错误(未定义)状态,从而需要更多麻烦。我强烈建议您使用copy & swap idiom

Applepie& Applepie::operator=(Applepie copy)
{
  swap(m_crust, copy.m_crust);
  swap(m_filling, copy.m_filling);
  return *this;
}

当你的对象也使用 Pimpl idiom (指向实现的指针)时,只需更改两个指针即可完成交换。

答案 1 :(得分:1)

除了Rene的回答之外,如果ApplePie是实际对象的基类,还会出现问题:ApplePie会用错误类型的对象替换对象!