在类body中使用unique_ptr作为同一个类的成员

时间:2016-11-17 12:18:42

标签: c++ c++11 compiler-errors destructor unique-ptr

以下是代码的极简主义问题:

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中找到此问题,但我确信它必须存在。随意标记为傻瓜。

3 个答案:

答案 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;