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

发布于 2024-12-01 05:25:42 字数 832 浏览 0 评论 0原文

背景: 我有一个包含许多变量的复杂类。我有一个健全且经过测试的复制构造函数:

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

初始化程序列表中调用的一些成员变量复制构造函数执行分配。

问题: 我需要创建 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;
}

换句话说,销毁 self 后跟一个放置新的复制构造函数,其语义与运算符相同= ?

这似乎有可能显着减少重复代码并确认每个变量都已正确初始化,但代价是分配期间可能会略有效率损失。我错过了一些更晦涩的东西吗?

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

Background:
I have a complicated class with many variables. I have a sound and tested copy constructor:

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

Some of the member variable copy constructors called in the intializer list perform allocation.

Question:
I need to create operator=. Rather than duplicating the existing constuctor with assignment instead of initialization list, and freeing memory that's being replaced, and etc etc etc, can I simply do the following:

Applepie& Applepie::operator=( const Applepie ©)
{
    if( this != ©)
    {
       this->~Applepie(); // release own object
       new(this) Applepie(copy); // placement new copy constructor
    }
    return *this;
}

In other words, is destroy self followed by a placement new copy constructor semantically identical to operator= ?

This seems to have the potential to dramatically reduce repeat code and confirming that each variable is initialized properly, at the cost of potential slight loss of efficiency during assignment. Am I missing something more obscure?

Rationale:
My actual class has about 30 varaibles. I am concerned about the fact that both my copy constructor and my assignment operator have to copy all thirty, and that the code might diverge, causing the two operations to do things differently.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情痴 2024-12-08 05:25:42

正如 Herb Sutter 在《Exceptional C++》中所说,它不是异常安全的。这意味着,如果在 new 或构造新对象期间出现任何问题,则赋值的左侧操作数将处于错误(未定义)状态,从而带来更多麻烦。我强烈建议使用 copy &交换习语

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

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

As Herb Sutter in "Exceptional C++" states, it is not exception safe. That means, if anything is going wrong during new or construction of the new object, the left hand operand of the assignment is in bad (undefined) state, calling for more trouble. I would strongly recommend using the copy & swap idiom.

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

When your object uses the Pimpl idiom (pointer to implementation) also, the swap is done by changing only two pointers.

江湖彼岸 2024-12-08 05:25:42

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

In addition to Rene's answer, there is also the problem of what would happen if ApplePie was a base class of the actual object: ApplePie would be replacing the object with an object of the wrong type!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文