Edit: made Foo
and Bar
稍微不那么琐碎,直接替换为shared_ptr<>
更加困难。
Should unique_ptr<>
用作实现移动语义的更简单方法?
对于像这样的课程
class Foo
{
int* m_pInts;
bool usedNew;
// other members ...
public:
Foo(size_t num, bool useNew=true) : usedNew(useNew) {
if (usedNew)
m_pInts = new int[num];
else
m_pInts = static_cast<int*>(calloc(num, sizeof(int)));
}
~Foo() {
if (usedNew)
delete[] m_pInts;
else
free(m_pInts);
}
// no copy, but move
Foo(const Foo&) = delete;
Foo& operator=(const Foo&) = delete;
Foo(Foo&& other) {
*this = std::move(other);
}
Foo& operator=(Foo&& other) {
m_pInts = other.m_pInts;
other.m_pInts = nullptr;
usedNew = other.usedNew;
return *this;
}
};
随着数据成员的添加,实施移动变得更加繁琐。但是,可移动数据可以放置在单独的struct
,其实例由unique_ptr<>
。这允许=default
用于移动:
class Bar
{
struct Data
{
int* m_pInts;
bool usedNew;
// other members ...
};
std::unique_ptr<Data> m_pData = std::make_unique<Data>();
public:
Bar(size_t num, bool useNew = true) {
m_pData->usedNew = useNew;
if (m_pData->usedNew)
m_pData->usedNew = new int[num];
else
m_pData->m_pInts = static_cast<int*>(calloc(num, sizeof(int)));
}
~Bar() {
if (m_pData->usedNew)
delete[] m_pData->m_pInts;
else
free(m_pData->m_pInts);
}
// no copy, but move
Bar(const Bar&) = delete;
Bar& operator=(const Bar&) = delete;
Bar(Bar&& other) = default;
Bar& operator=(Bar&& other) = default;
};
除了内存之外unique_ptr<>
实例始终位于堆上,这样的实现还存在哪些其他问题?
是的。您正在寻找的称为“零规则”(作为“三/五规则”的 C++11 扩展)。通过让您的数据都知道如何复制和移动自身,外部类不需要编写any的特殊成员函数。编写这些特殊成员可能很容易出错,因此不必编写它们可以解决很多问题。
So Foo
会变成:
class Foo
{
std::unique_ptr<size_t[]> data;
public:
Foo(size_t size): data(new size_t[size]) { }
};
这很容易证明其正确性。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)