显式调用unique_ptr内对象的复制构造函数



我使用带有const std::unique_ptr的pimpl习惯用法来保存类实现。我的班级需要支持复印构造和复印作业。我想做的是手动调用unique_ptrimpl类的复制构造函数。然而,我不知道该怎么做。

#include <memory>
struct potato {
potato();
~potato();
potato(const potato& p);
private:
struct impl;
const std::unique_ptr<impl> _pimpl;
};
struct potato::impl {
int carbs = 42;
};
potato::potato()
: _pimpl(std::make_unique<impl>()) {
}
potato::~potato() = default;
potato::potato(const potato& p) {
// Try to call the copy constructor of impl, stored in unique_ptr, not the
// unique_ptr copy-constructor (which doesn't exist).
_pimpl.get()->impl(p._pimpl); // This doesn't work.
}

我检查了另一个关于在对象上显式调用复制构造函数的问题。一个答案建议使用新位置。

Object dstObject;
new(&dstObject) Object(&anotherObject);

我可以在复制构造函数中使用它吗?如果是,如何?我真的不明白那里发生了什么。非常感谢。

我想做的是手动调用unique_ptrimpl类的复制构造函数

您的错误就在这里。由于您在potato的(复制(构造函数中,没有已经构建的impl对象,您必须"手动"调用复制构造函数。

只需构造新的impl,并向其传递对要复制的原始impl的引用。

potato::potato(const potato& p)
: _pimpl(std::make_unique<impl>(*p._pimpl) {
}

关于分配,您可以很容易地转发给impl分配操作员:

potato &operator=(const potato &p) {
*_pimpl = *p._pimpl;
return *this;
}

您可以使用placementnew操作符在未初始化的存储上显式调用构造函数,正如您所提到的。通过显式调用对象的析构函数,可以将对象的存储返回到未初始化状态。

下面是赋值运算符的一个简单实现,它显式调用复制构造函数和您已经定义为接口一部分的析构函数:

#include <new>
potato& potato::operator=(const potato& x)
{
if ( this != &x ) { // check for self-assignment!
this->~potato();
new(this) potato(x);
}
return *this;
}

您可能还想定义一个move构造函数,并在右侧是临时运算符时重载赋值运算符。即potato&& srcconst potato& src的过载。如果您的类支持交换习惯用法,您可以使用它,或者使用与上面相同的代码,但调用new(this) potato(std::move(src));

如果您可以访问封装在智能指针中的类的析构函数和复制构造函数,则可以对它们执行相同的操作,只需取消对智能指针的引用。不过你可能不想。

如果类的内容是智能指针、STL容器等,默认的复制构造函数和赋值运算符应该可以正常工作。您可能希望通过编写*p = x*p = *qstd::swap之类的内容来复制智能指针引用的数据,而不是显式调用复制构造函数。

相关内容

  • 没有找到相关文章

最新更新