编辑:制作Foo
和 Bar
不那么琐碎,直接替换为 shared_ptr<>
更难。
应该unique_ptr<>
用作实现 move 语义的更简单方法?
对于像这样的类
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;
}
};
随着数据成员的增加,实现 move 变得更加乏味。但是,可 move 数据可以放在单独的 struct
中。 ,其中一个实例由 unique_ptr<>
管理.这允许 =default
用于 move :
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 扩展)。通过让您的数据都知道如何复制和 move 它们自己,外部类不需要编写任何 特殊成员函数。编写这些特殊成员可能容易出错,因此不必编写它们可以解决很多问题。
所以 Foo
会变成:
class Foo
{
std::unique_ptr<size_t[]> data;
public:
Foo(size_t size): data(new size_t[size]) { }
};
而且这很容易证明其正确性。
关于c++ - 是否应该使用 unique_ptr 来更轻松地实现 "move"语义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40851598/