以下是代码的极简主义问题:
struct B {
B () = default;
//~B () {}; // error: use of deleted function ‘B& B::operator=(const B&)’
std::unique_ptr<int> m_pB = nullptr;
};
int main ()
{
std::vector<B> vB;
vB.erase(vB.begin());
}
上面的代码编译很好,除非析构函数被取消注释。根据我的要求,我需要明确定义~B()
的正文。
如何在同一个类中共存unique_ptr
来定义析构函数体?
注意:尝试定义= default
版本的copy&amp;移动构造函数无济于事。在我的真实代码中,unique_ptr<int>
是unique_ptr<forward_declared_class>
。无法在SO中找到此问题,但我确信它必须存在。随意标记为傻瓜。
答案 0 :(得分:5)
似乎您的代码需要B
可复制构造并且可以为std::vector
分配复制(至少对于我测试过的visual c ++)。
复制构造函数和复制分配运算符只能是= delete
,因为std::unique_ptr
(声明= default
的实现也会导致函数被删除),并且通过实现析构函数,你禁用移动构造函数和移动赋值运算符的默认实现。
因此,您需要显式声明移动赋值运算符。尝试:
#include <memory>
#include <vector>
struct B {
B () = default;
~B () {}
B& operator=(B&&) = default;
std::unique_ptr<int> m_pB = nullptr;
};
int main ()
{
std::vector<B> vB;
vB.erase(vB.begin());
}
答案 1 :(得分:3)
您可以声明并实现编译器要求的移动赋值运算符。当然,它抱怨复制作业,但你的结构似乎不可能有一个合理的副本。
可能错误消息有点误导,因为std::vector::erase
实现在代码中包含类似_data[i-1] = _data[i]
的内容,它将向量元素发送到已删除项目的位置。所以编译器需要任何赋值运算符,我们为它提供一个移动运算符。
例如,这工作正常(gcc 4.8.3):
struct B {
B () = default;
B& operator=(B&& op) {
m_pB = std::move(op.m_pB);
return *this;
}
~B () {}; // no more errors.
std::unique_ptr<int> m_pB = nullptr;
};
int main ()
{
std::vector<B> vB;
vB.erase(vB.begin());
}
答案 2 :(得分:0)
矢量代码是红鲱鱼。
当类U具有unique_ptr类型的成员,并且T是前向声明的时,析构函数的定义必须在cpp文件中,而U不再是不完整类型。
你应该有~U();在头文件中,在cpp文件中有U :: ~U(){}或U :: ~U()= default;